for review: new method of handling failures, part 4a of 6
Zoltan Somogyi
zs at cs.mu.OZ.AU
Thu Jul 2 16:31:15 AEST 1998
Apparently part 4, which contained just the diff to code_info.m,
was more than 100 kb!, and hence bounced. Here it is in two halves.
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.223
diff -u -r1.223 code_info.m
--- code_info.m 1998/06/18 06:05:53 1.223
+++ code_info.m 1998/07/01 11:58:48
@@ -11,10 +11,11 @@
% This file defines the code_info type and various operations on it.
% The code_info structure is the 'state' of the code generator.
%
-% This file is organized into eight submodules:
+% This file is organized into nine submodules:
%
% - the code_info structure and its access predicates
% - simple wrappers around access predicates
+% - handling branched control structures
% - handling failure continuations
% - handling liveness issues
% - saving and restoring heap pointers, trail tickets etc
@@ -22,11 +23,6 @@
% - managing the info required by garbage collection and value numbering
% - managing stack slots
%
-% Note: Any new "state" arguments (eg counters) that should be strictly
-% threaded (for example the counter used for allocating new labels) will
-% require changes to code_info__slap_code_info/3.
-%
-%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module code_info.
@@ -45,6 +41,7 @@
:- import_module set, varset, stack.
:- import_module string, require, char, bimap, tree, int.
+:- import_module unsafe, io.
%---------------------------------------------------------------------------%
@@ -68,13 +65,17 @@
% Create a new code_info structure.
:- pred code_info__init(varset, set(var), stack_slots, bool, globals,
pred_id, proc_id, proc_info, instmap, follow_vars, module_info,
- int /* cell number */, code_info).
+ int, resume_point_info, code_info).
:- mode code_info__init(in, in, in, in, in, in, in, in, in, in, in, in,
- out) is det.
+ out, out) is det.
- % Get the variables for the current procedure.
-:- pred code_info__get_varset(varset, code_info, code_info).
-:- mode code_info__get_varset(out, in, out) is det.
+ % Get the globals table.
+:- pred code_info__get_globals(globals, code_info, code_info).
+:- mode code_info__get_globals(out, in, out) is det.
+
+ % Get the HLDS of the entire module.
+:- pred code_info__get_module_info(module_info, code_info, code_info).
+:- mode code_info__get_module_info(out, in, out) is det.
% Get the id of the predicate we are generating code for.
:- pred code_info__get_pred_id(pred_id, code_info, code_info).
@@ -88,13 +89,13 @@
:- pred code_info__get_proc_info(proc_info, code_info, code_info).
:- mode code_info__get_proc_info(out, in, out) is det.
- % Get the flag that indicates whether succip is used or not.
-:- pred code_info__get_succip_used(bool, code_info, code_info).
-:- mode code_info__get_succip_used(out, in, out) is det.
+ % Get the variables for the current procedure.
+:- pred code_info__get_varset(varset, code_info, code_info).
+:- mode code_info__get_varset(out, in, out) is det.
- % Get the HLDS of the entire module.
-:- pred code_info__get_module_info(module_info, code_info, code_info).
-:- mode code_info__get_module_info(out, in, out) is det.
+:- pred code_info__get_maybe_trace_info(maybe(trace_info),
+ code_info, code_info).
+:- mode code_info__get_maybe_trace_info(out, in, out) is det.
% Get the set of currently forward-live variables.
:- pred code_info__get_forward_live_vars(set(var), code_info, code_info).
@@ -114,22 +115,17 @@
:- pred code_info__set_instmap(instmap, code_info, code_info).
:- mode code_info__set_instmap(in, in, out) is det.
- % Get the globals table.
-:- pred code_info__get_globals(globals, code_info, code_info).
-:- mode code_info__get_globals(out, in, out) is det.
+:- pred code_info__get_cell_count(int, code_info, code_info).
+:- mode code_info__get_cell_count(out, in, out) is det.
+
+ % Get the flag that indicates whether succip is used or not.
+:- pred code_info__get_succip_used(bool, code_info, code_info).
+:- mode code_info__get_succip_used(out, in, out) is det.
:- pred code_info__get_layout_info(map(label, internal_layout_info),
- code_info, code_info).
+ code_info, code_info).
:- mode code_info__get_layout_info(out, in, out) is det.
-:- pred code_info__get_maybe_trace_info(maybe(trace_info),
- code_info, code_info).
-:- mode code_info__get_maybe_trace_info(out, in, out) is det.
-
-:- pred code_info__set_maybe_trace_info(maybe(trace_info),
- code_info, code_info).
-:- mode code_info__set_maybe_trace_info(in, in, out) is det.
-
%---------------------------------------------------------------------------%
:- implementation.
@@ -137,14 +133,15 @@
:- pred code_info__get_var_slot_count(int, code_info, code_info).
:- mode code_info__get_var_slot_count(out, in, out) is det.
-:- pred code_info__get_label_count(int, code_info, code_info).
-:- mode code_info__get_label_count(out, in, out) is det.
+:- pred code_info__set_maybe_trace_info(maybe(trace_info),
+ code_info, code_info).
+:- mode code_info__set_maybe_trace_info(in, in, out) is det.
-:- pred code_info__set_label_count(int, code_info, code_info).
-:- mode code_info__set_label_count(in, in, out) is det.
+:- pred code_info__get_zombies(set(var), code_info, code_info).
+:- mode code_info__get_zombies(out, in, out) is det.
-:- pred code_info__set_cell_count(int, code_info, code_info).
-:- mode code_info__set_cell_count(in, in, out) is det.
+:- pred code_info__set_zombies(set(var), code_info, code_info).
+:- mode code_info__set_zombies(in, in, out) is det.
:- pred code_info__get_exprn_info(exprn_info, code_info, code_info).
:- mode code_info__get_exprn_info(out, in, out) is det.
@@ -152,27 +149,6 @@
:- pred code_info__set_exprn_info(exprn_info, code_info, code_info).
:- mode code_info__set_exprn_info(in, in, out) is det.
-:- pred code_info__set_succip_used(bool, code_info, code_info).
-:- mode code_info__set_succip_used(in, in, out) is det.
-
-:- pred code_info__get_fail_stack(fail_stack, code_info, code_info).
-:- mode code_info__get_fail_stack(out, in, out) is det.
-
-:- pred code_info__set_fail_stack(fail_stack, code_info, code_info).
-:- mode code_info__set_fail_stack(in, in, out) is det.
-
-:- pred code_info__get_avail_temp_slots(set(lval), code_info, code_info).
-:- mode code_info__get_avail_temp_slots(out, in, out) is det.
-
-:- pred code_info__set_avail_temp_slots(set(lval), code_info, code_info).
-:- mode code_info__set_avail_temp_slots(in, in, out) is det.
-
-:- pred code_info__get_max_temp_slot_count(int, code_info, code_info).
-:- mode code_info__get_max_temp_slot_count(out, in, out) is det.
-
-:- pred code_info__set_max_temp_slot_count(int, code_info, code_info).
-:- mode code_info__set_max_temp_slot_count(in, in, out) is det.
-
:- pred code_info__get_temps_in_use(map(lval, slot_contents),
code_info, code_info).
:- mode code_info__get_temps_in_use(out, in, out) is det.
@@ -181,107 +157,114 @@
code_info, code_info).
:- mode code_info__set_temps_in_use(in, in, out) is det.
-:- pred code_info__set_layout_info(map(label, internal_layout_info),
- code_info, code_info).
-:- mode code_info__set_layout_info(in, in, out) is det.
+:- pred code_info__get_fail_info(fail_info, code_info, code_info).
+:- mode code_info__get_fail_info(out, in, out) is det.
-:- pred code_info__get_zombies(set(var), code_info, code_info).
-:- mode code_info__get_zombies(out, in, out) is det.
+:- pred code_info__set_fail_info(fail_info, code_info, code_info).
+:- mode code_info__set_fail_info(in, in, out) is det.
-:- pred code_info__set_zombies(set(var), code_info, code_info).
-:- mode code_info__set_zombies(in, in, out) is det.
+:- pred code_info__get_label_count(int, code_info, code_info).
+:- mode code_info__get_label_count(out, in, out) is det.
-:- pred code_info__get_resume_point_stack(stack(set(var)),
- code_info, code_info).
-:- mode code_info__get_resume_point_stack(out, in, out) is det.
+:- pred code_info__set_label_count(int, code_info, code_info).
+:- mode code_info__set_label_count(in, in, out) is det.
+
+:- pred code_info__set_cell_count(int, code_info, code_info).
+:- mode code_info__set_cell_count(in, in, out) is det.
+
+:- pred code_info__set_succip_used(bool, code_info, code_info).
+:- mode code_info__set_succip_used(in, in, out) is det.
-:- pred code_info__set_resume_point_stack(stack(set(var)),
+:- pred code_info__set_layout_info(map(label, internal_layout_info),
code_info, code_info).
-:- mode code_info__set_resume_point_stack(in, in, out) is det.
+:- mode code_info__set_layout_info(in, in, out) is det.
+
+:- pred code_info__get_max_temp_slot_count(int, code_info, code_info).
+:- mode code_info__get_max_temp_slot_count(out, in, out) is det.
+
+:- pred code_info__set_max_temp_slot_count(int, code_info, code_info).
+:- mode code_info__set_max_temp_slot_count(in, in, out) is det.
-:- pred code_info__get_commit_triple_count(int, code_info, code_info).
-:- mode code_info__get_commit_triple_count(out, in, out) is det.
+:- pred code_info__get_avail_temp_slots(set(lval), code_info, code_info).
+:- mode code_info__get_avail_temp_slots(out, in, out) is det.
-:- pred code_info__set_commit_triple_count(int, code_info, code_info).
-:- mode code_info__set_commit_triple_count(in, in, out) is det.
+:- pred code_info__set_avail_temp_slots(set(lval), code_info, code_info).
+:- mode code_info__set_avail_temp_slots(in, in, out) is det.
%---------------------------------------------------------------------------%
+ % The code_info structure has three groups of fields.
+ %
+ % Some fields are static; they are set when the code_info structure
+ % is initialized, and never changed afterwards.
+ %
+ % Some fields record information about the state of the code generator
+ % at a particular location in the HLDS code of the current procedure.
+ % At the start of the branched control structure, the code generator
+ % remembers the values of these fields, and starts generating code
+ % for each branch from the same location-dependent state.
+ %
+ % Some fields record persistent information that does not depend
+ % on a code location. Updates to these fields must remain effective
+ % even when the code generator resets its location-dependent state.
+
:- type code_info --->
- code_info(
- int, % The number of stack slots allocated.
- % for storing variables.
- % (Some extra stack slots are used
- % for saving and restoring registers.)
- int, % Counter for the local labels used
- % by this procedure.
- varset, % The variables in this procedure.
- pred_id, % The label of the current predicate.
- proc_id, % The label of the current procedure.
- int, % Counter for cells in this proc.
- exprn_info, % A map storing the information about
- % the status of each variable.
- proc_info, % The proc_info for the this procedure.
- bool, % do we need to store succip?
- fail_stack, % The failure continuation stack
- module_info, % The module_info structure - you just
- % never know when you might need it.
- % It should be read-only.
- set(var), % Variables that are forward live
- % after this goal
- instmap, % insts of variables
- set(lval), % Stack variables that have been used
- % for temporaries and are now again
- % available for reuse.
- int, % The maximum number of extra
- % temporary stackslots that have been
- % used during the procedure
- globals, % code generation options
- map(lval, slot_contents),
- % The temp locations in use on the stack
- % and what they contain (for gc).
- map(label, internal_layout_info),
- % Information on which values
- % are live and where at which labels,
- % for tracing and/or accurate gc.
- set(var), % Zombie variables; variables that have
- % been killed but are protected by a
- % resume point.
- stack(set(var)),
- % Each resumption point has an
- % associated set of variables
- % whose values may be needed on
- % resumption at that point.
- % This field gives those variables
- % for a nested set of resumption
- % points. Each element must be
- % a superset of the ones below.
- % When a variable included in the top
- % set becomes no longer forward live,
- % we must save its value to the stack.
- int,
- % A count of how many triples of
- % curfr, maxfr and redoip are live on
- % the det stack. These triples are
- % pushed onto the det stack when
- % generating code for commits within
- % model_non procedures. The value
- % numbering pass and the accurate
- % garbage collector need to know about
- % these slots. (Triple is a misnomer:
- % in grades with trailing, it is four.)
- maybe(trace_info)
- % Information about which stack slots
- % the call sequence number and depth
- % are stored, provided tracing is
- % switched on.
+ code_info(
+ % STATIC fields
+ globals, % For the code generation options.
+ module_info, % The module_info structure - you just
+ % never know when you might need it.
+ pred_id, % The id of the current predicate.
+ proc_id, % The id of the current procedure.
+ proc_info, % The proc_info for the this procedure.
+ varset, % The variables in this procedure.
+ int, % The number of stack slots allocated.
+ % for storing variables.
+ % (Some extra stack slots are used
+ % for saving and restoring registers.)
+ maybe(trace_info),
+ % Information about which stack slots
+ % the call sequence number and depth
+ % are stored, provided tracing is
+ % switched on.
+
+ % LOCATION DEPENDENT fields
+ set(var), % Variables that are forward live
+ % after this goal.
+ instmap, % Current insts of the live variables.
+ set(var), % Zombie variables; variables that are not
+ % forward live but which are protected by
+ % an enclosing resume point.
+ exprn_info, % A map storing the information about
+ % the status of each known variable.
+ % (Known vars = forward live vars + zombies)
+ map(lval, slot_contents),
+ % The temp locations in use on the stack
+ % and what they contain (for gc).
+ fail_info, % Information about how to manage failures.
+
+ % PERSISTENT fields
+ int, % Counter for the local labels used
+ % by this procedure.
+ int, % Counter for cells in this proc.
+ bool, % do we need to store succip?
+ map(label, internal_layout_info),
+ % Information on which values
+ % are live and where at which labels,
+ % for tracing. Accurate gc
+ int, % The maximum number of extra
+ % temporary stackslots that have been
+ % used during the procedure.
+ set(lval) % Stack variables that have been used
+ % for temporaries and are now again
+ % available for reuse.
).
%---------------------------------------------------------------------------%
code_info__init(Varset, Liveness, StackSlots, SaveSuccip, Globals,
- PredId, ProcId, ProcInfo, Requests, FollowVars,
- ModuleInfo, CellCount, C) :-
+ PredId, ProcId, ProcInfo, Instmap, FollowVars,
+ ModuleInfo, CellCount, ResumePoint, CodeInfo) :-
proc_info_headvars(ProcInfo, HeadVars),
proc_info_arg_info(ProcInfo, ArgInfos),
assoc_list__from_corresponding_lists(HeadVars, ArgInfos, Args),
@@ -289,12 +272,13 @@
globals__get_options(Globals, Options),
code_exprn__init_state(ArgList, Varset, StackSlots, FollowVars,
Options, ExprnInfo),
- stack__init(Continue),
- stack__init(ResumeSetStack0),
- set__init(AvailSlots0),
- map__init(TempsInUse0),
- set__init(Zombies0),
- map__init(Shapes),
+ stack__init(ResumePoints),
+ DummyFailInfo = fail_info(ResumePoints, resume_point_unknown,
+ may_be_different),
+ set__init(AvailSlots),
+ map__init(TempsInUse),
+ set__init(Zombies),
+ map__init(LayoutMap),
code_info__max_var_slot(StackSlots, VarSlotCount0),
proc_info_interface_code_model(ProcInfo, CodeModel),
(
@@ -304,289 +288,212 @@
;
VarSlotCount = VarSlotCount0
),
- C = code_info(
- VarSlotCount,
- 0,
- Varset,
+ CodeInfo0 = code_info(
+ Globals,
+ ModuleInfo,
PredId,
ProcId,
- CellCount,
- ExprnInfo,
ProcInfo,
- SaveSuccip,
- Continue,
- ModuleInfo,
+ Varset,
+ VarSlotCount,
+ no,
+
Liveness,
- Requests,
- AvailSlots0,
+ Instmap,
+ Zombies,
+ ExprnInfo,
+ TempsInUse,
+ DummyFailInfo, % code_info__init_fail_info
+ % will override this dummy value
0,
- Globals,
- TempsInUse0,
- Shapes,
- Zombies0,
- ResumeSetStack0,
+ CellCount,
+ SaveSuccip,
+ LayoutMap,
0,
- no
- ).
-
-%---------------------------------------------------------------------------%
-
-code_info__get_var_slot_count(A, CI, CI) :-
- CI = code_info(A, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_label_count(B, CI, CI) :-
- CI = code_info(_, B, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_varset(C, CI, CI) :-
- CI = code_info(_, _, C, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_pred_id(D, CI, CI) :-
- CI = code_info(_, _, _, D, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_proc_id(E, CI, CI) :-
- CI = code_info(_, _, _, _, E, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_cell_count(F, CI, CI) :-
- CI = code_info(_, _, _, _, _, F, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_exprn_info(G, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, G, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_proc_info(H, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, H, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_succip_used(I, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, I, _, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_fail_stack(J, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, J, _, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_module_info(K, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, K, _, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_forward_live_vars(L, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, L, _, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_instmap(M, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, M, _, _, _, _, _, _,
- _, _, _).
-
-code_info__get_avail_temp_slots(N, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, N, _, _, _, _, _,
- _, _, _).
-
-code_info__get_max_temp_slot_count(O, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, O, _, _, _, _,
- _, _, _).
-
-code_info__get_globals(P, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, P, _, _, _,
- _, _, _).
-
-code_info__get_temps_in_use(Q, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, Q, _, _,
- _, _, _).
-
-code_info__get_layout_info(R, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, R, _,
- _, _, _).
-
-code_info__get_zombies(S, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, S,
- _, _, _).
-
-code_info__get_resume_point_stack(T, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- T, _, _).
-
-code_info__get_commit_triple_count(U, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, U, _).
-
-code_info__get_maybe_trace_info(V, CI, CI) :-
- CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, V).
-
-% :- type code_info --->
-% code_info(
-% A int, % The number of stack slots allocated.
-% % for storing variables.
-% % (Some extra stack slots are used
-% % for saving and restoring registers.)
-% B int, % Counter for the local labels used
-% % by this procedure.
-% C varset, % The variables in this procedure.
-% D pred_id, % The label of the current predicate.
-% E proc_id, % The label of the current procedure.
-% F int, % Counter for cells in this proc.
-% G exprn_info, % A map storing the information about
-% % the status of each variable.
-% H proc_info, % The proc_info for the this procedure.
-% I bool, % do we need to store succip?
-% J fail_stack, % The failure continuation stack
-% K module_info, % The module_info structure - you just
-% % never know when you might need it.
-% % It should be read-only.
-% L set(var), % Variables that are forward live
-% % after this goal
-% M instmap, % insts of variables
-% N set(lval), % Stack variables that have been used
-% % for temporaries and are now again
-% % available for reuse.
-% O int, % The maximum number of extra
-% % temporary stackslots that have been
-% % used during the procedure
-% P globals, % code generation options
-% Q map(lval, slot_contents),
-% % The temp locations in use on the stack
-% % and what they contain (for gc).
-% R map(label, internal_layout_info),
-% % Information on which values
-% % are live and where at which labels,
-% % for tracing and/or accurate gc.
-% S set(var), % Zombie variables; variables that have
-% % been killed but are protected by a
-% % resume point.
-% T stack(set(var)),
-% % Each resumption point has an
-% % associated set of variables
-% % whose values may be needed on
-% % resumption at that point.
-% % This field gives those variables
-% % for a nested set of resumption
-% % points. Each element must be
-% % a superset of the ones below.
-% % When a variable included in the top
-% % set becomes no longer forward live,
-% % we must save its value to the stack.
-% U int,
-% % A count of how many triples of
-% % curfr, maxfr and redoip are live on
-% % the det stack. These triples are
-% % pushed onto the det stack when
-% % generating code for commits within
-% % model_non procedures. The value
-% % numbering pass and the accurate
-% % garbage collector need to know about
-% % these slots. (Triple is a misnomer:
-% % in grades with trailing, it is four.)
-% V maybe(trace_info)
-% % Information about which stack slots
-% % the call sequence number and depth
-% % are stored, provided tracing is
-% % switched on.
-% ).
-%
-% we don't need
-% code_info__set_var_slot_count
-% code_info__set_varset
-% code_info__set_pred_id
-% code_info__set_proc_id
-% code_info__set_module_info
-% code_info__set_globals
-% code_info__set_code_model
-
-code_info__set_label_count(B, CI0, CI) :-
- CI0 = code_info(A, _, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_cell_count(F, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, _, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_exprn_info(G, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, _, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_succip_used(I, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, _, J, K, L, M, N, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_fail_stack(J, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, _, K, L, M, N, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_forward_live_vars(L, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, _, M, N, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_instmap(M, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, _, N, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_avail_temp_slots(N, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, _, O, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_max_temp_slot_count(O, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, _, P, Q,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_temps_in_use(Q, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, _,
- R, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_layout_info(R, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- _, S, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_zombies(S, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, _, T, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_resume_point_stack(T, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, _, U, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_commit_triple_count(U, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, _, V),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
-
-code_info__set_maybe_trace_info(V, CI0, CI) :-
- CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, _),
- CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
- R, S, T, U, V).
+ AvailSlots
+ ),
+ globals__get_trace_level(Globals, TraceLevel),
+ code_info__init_maybe_trace_info(TraceLevel, ModuleInfo, ProcInfo,
+ MaybeFailVars, CodeInfo0, CodeInfo1),
+ code_info__init_fail_info(CodeModel, MaybeFailVars, ResumePoint,
+ CodeInfo1, CodeInfo).
+
+:- pred code_info__init_maybe_trace_info(trace_level, module_info, proc_info,
+ maybe(set(var)), code_info, code_info).
+:- mode code_info__init_maybe_trace_info(in, in, in, out, in, out) is det.
+
+code_info__init_maybe_trace_info(TraceLevel, ModuleInfo, ProcInfo,
+ MaybeFailVars) -->
+ ( { trace_level_trace_interface(TraceLevel, yes) } ->
+ trace__setup(TraceLevel, TraceInfo),
+ code_info__set_maybe_trace_info(yes(TraceInfo)),
+ { trace__fail_vars(ModuleInfo, ProcInfo, FailVars) },
+ { MaybeFailVars = yes(FailVars) }
+ ;
+ { MaybeFailVars = no }
+ ).
+
+%---------------------------------------------------------------------------%
+
+code_info__get_globals(SA, CI, CI) :-
+ CI = code_info(SA, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_module_info(SB, CI, CI) :-
+ CI = code_info(_, SB, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_pred_id(SC, CI, CI) :-
+ CI = code_info(_, _, SC, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_proc_id(SD, CI, CI) :-
+ CI = code_info(_, _, _, SD, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_proc_info(SE, CI, CI) :-
+ CI = code_info(_, _, _, _, SE, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_varset(SF, CI, CI) :-
+ CI = code_info(_, _, _, _, _, SF, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_var_slot_count(SG, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, SG, _,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_maybe_trace_info(SH, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, SH,
+ _, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_forward_live_vars(LA, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ LA, _, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_instmap(LB, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, LB, _, _, _, _, _, _, _, _, _, _).
+
+code_info__get_zombies(LC, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, LC, _, _, _, _, _, _, _, _, _).
+
+code_info__get_exprn_info(LD, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, LD, _, _, _, _, _, _, _, _).
+
+code_info__get_temps_in_use(LE, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, LE, _, _, _, _, _, _, _).
+
+code_info__get_fail_info(LF, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, LF, _, _, _, _, _, _).
+
+code_info__get_label_count(PA, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, PA, _, _, _, _, _).
+
+code_info__get_cell_count(PB, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, PB, _, _, _, _).
+
+code_info__get_succip_used(PC, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, PC, _, _, _).
+
+code_info__get_layout_info(PD, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, PD, _, _).
+
+code_info__get_max_temp_slot_count(PE, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, PE, _).
+
+code_info__get_avail_temp_slots(PF, CI, CI) :-
+ CI = code_info(_, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, PF).
+
+%---------------------------------------------------------------------------%
+
+code_info__set_maybe_trace_info(SH, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, _,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_forward_live_vars(LA, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ _, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_instmap(LB, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, _, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_zombies(LC, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, _, LD, LE, LF, PA, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_exprn_info(LD, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, _, LE, LF, PA, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_temps_in_use(LE, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, _, LF, PA, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_fail_info(LF, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, _, PA, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_label_count(PA, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, _, PB, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_cell_count(PB, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, _, PC, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_succip_used(PC, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, _, PD, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_layout_info(PD, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, _, PE, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_max_temp_slot_count(PE, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, _, PF),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
+
+code_info__set_avail_temp_slots(PF, CI0, CI) :-
+ CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, _ ),
+ CI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -631,7 +538,7 @@
% Given a list of type variables, find the lvals where the
% corresponding type_infos and typeclass_infos are being stored.
-:- pred code_info__find_type_infos(list(var), assoc_list(var, lval),
+:- pred code_info__find_type_infos(list(var), assoc_list(var, lval),
code_info, code_info).
:- mode code_info__find_type_infos(in, out, in, out) is det.
@@ -657,25 +564,9 @@
code_info, code_info).
:- mode code_info__get_pred_proc_arginfo(in, in, out, in, out) is det.
- % Pop the failure continuation stack.
-:- pred code_info__pop_failure_cont(code_info, code_info).
-:- mode code_info__pop_failure_cont(in, out) is det.
-
-:- pred code_info__push_resume_point_vars(set(var), code_info, code_info).
-:- mode code_info__push_resume_point_vars(in, in, out) is det.
-
-:- pred code_info__pop_resume_point_vars(code_info, code_info).
-:- mode code_info__pop_resume_point_vars(in, out) is det.
-
:- pred code_info__variable_to_string(var, string, code_info, code_info).
:- mode code_info__variable_to_string(in, out, in, out) is det.
-:- pred code_info__grab_code_info(code_info, code_info, code_info).
-:- mode code_info__grab_code_info(out, in, out) is det.
-
-:- pred code_info__slap_code_info(code_info, code_info, code_info).
-:- mode code_info__slap_code_info(in, in, out) is det.
-
:- pred code_info__apply_instmap_delta(instmap_delta, code_info, code_info).
:- mode code_info__apply_instmap_delta(in, in, out) is det.
@@ -701,10 +592,6 @@
:- pred code_info__get_next_cell_number(int, code_info, code_info).
:- mode code_info__get_next_cell_number(out, in, out) is det.
- % Get the current cell number.
-:- pred code_info__get_cell_count(int, code_info, code_info).
-:- mode code_info__get_cell_count(out, in, out) is det.
-
:- pred code_info__succip_is_used(code_info, code_info).
:- mode code_info__succip_is_used(in, out) is det.
@@ -716,25 +603,6 @@
:- implementation.
-:- pred code_info__push_failure_cont(failure_cont, code_info, code_info).
-:- mode code_info__push_failure_cont(in, in, out) is det.
-
- % Lookup the value on the top of the failure continuation stack
-
-:- pred code_info__top_failure_cont(failure_cont, code_info, code_info).
-:- mode code_info__top_failure_cont(out, in, out) is det.
-
-:- pred code_info__current_resume_point_vars(set(var), code_info, code_info).
-:- mode code_info__current_resume_point_vars(out, in, out) is det.
-
-:- pred code_info__add_commit_triple(code_info, code_info).
-:- mode code_info__add_commit_triple(in, out) is det.
-
-:- pred code_info__rem_commit_triple(code_info, code_info).
-:- mode code_info__rem_commit_triple(in, out) is det.
-
-%-----------------------------------------------------------------------------%
-
code_info__get_stack_slots(StackSlots, CI, CI) :-
code_info__get_exprn_info(ExprnInfo, CI, _),
code_exprn__get_stack_slots(StackSlots, ExprnInfo, _).
@@ -872,64 +740,16 @@
%---------------------------------------------------------------------------%
-code_info__push_failure_cont(Cont) -->
- code_info__get_fail_stack(Fall0),
- { stack__push(Fall0, Cont, Fall) },
- code_info__set_fail_stack(Fall).
-
-code_info__pop_failure_cont -->
- code_info__get_fail_stack(Fall0),
- ( { stack__pop(Fall0, _, Fall) } ->
- code_info__set_fail_stack(Fall)
- ;
- { error("code_info__pop_failure_cont: empty stack") }
- ).
-
-code_info__top_failure_cont(Cont) -->
- code_info__get_fail_stack(Fall),
- ( { stack__top(Fall, Cont0) } ->
- { Cont = Cont0 }
- ;
- { error("code_info__failure_cont: no failure continuation") }
- ).
-
-%---------------------------------------------------------------------------%
+:- pred code_info__current_resume_point_vars(set(var), code_info, code_info).
+:- mode code_info__current_resume_point_vars(out, in, out) is det.
code_info__current_resume_point_vars(ResumeVars) -->
- code_info__get_resume_point_stack(ResumeStack),
- { stack__top(ResumeStack, TopVars) ->
- ResumeVars = TopVars
- ;
- set__init(ResumeVars)
- }.
-
-code_info__push_resume_point_vars(ResumeVars) -->
- code_info__get_resume_point_stack(ResumeStack0),
- { stack__top(ResumeStack0, OldTopVars) ->
- require(set__subset(OldTopVars, ResumeVars),
- "new resume point variable set does not include old one")
- ;
- true
- },
- { stack__push(ResumeStack0, ResumeVars, ResumeStack) },
- code_info__set_resume_point_stack(ResumeStack).
-
-code_info__pop_resume_point_vars -->
- code_info__get_resume_point_stack(ResumeStack0),
- { stack__pop_det(ResumeStack0, _, ResumeStack) },
- code_info__set_resume_point_stack(ResumeStack).
-
-%---------------------------------------------------------------------------%
-
-code_info__add_commit_triple -->
- code_info__get_commit_triple_count(Count0),
- { Count is Count0 + 1 },
- code_info__set_commit_triple_count(Count).
-
-code_info__rem_commit_triple -->
- code_info__get_commit_triple_count(Count0),
- { Count is Count0 - 1 },
- code_info__set_commit_triple_count(Count).
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePointStack, _, _) },
+ { stack__top_det(ResumePointStack, ResumePointInfo) },
+ { code_info__pick_first_resume_point(ResumePointInfo, ResumeMap, _) },
+ { map__keys(ResumeMap, ResumeMapVarList) },
+ { set__list_to_set(ResumeMapVarList, ResumeVars) }.
%---------------------------------------------------------------------------%
@@ -937,24 +757,6 @@
code_info__get_varset(Varset),
{ varset__lookup_name(Varset, Var, Name) }.
-code_info__grab_code_info(C, C, C).
-
-code_info__slap_code_info(C0, C1, C) :-
- code_info__get_label_count(L, C1, _),
- code_info__set_label_count(L, C0, C2),
- code_info__get_succip_used(S, C1, _),
- code_info__set_succip_used(S, C2, C3),
- code_info__get_fail_stack(J, C0, _),
- code_info__set_fail_stack(J, C3, C4),
- code_info__get_max_temp_slot_count(PC, C1, _),
- code_info__set_max_temp_slot_count(PC, C4, C5),
- code_info__get_avail_temp_slots(TS, C1, _),
- code_info__set_avail_temp_slots(TS, C5, C6),
- code_info__get_layout_info(LayoutInfo, C1, _),
- code_info__set_layout_info(LayoutInfo, C6, C7),
- code_info__get_cell_count(CellCount, C1, _),
- code_info__set_cell_count(CellCount, C7, C).
-
code_info__apply_instmap_delta(Delta) -->
code_info__get_instmap(InstMap0),
{ instmap__apply_instmap_delta(InstMap0, Delta, InstMap) },
@@ -1016,670 +818,673 @@
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
- % Submodule for the handling of failure continuations.
+ % Submodule for handling branched control structures.
:- interface.
- % We manufacture a failure cont when we start generating
- % code for a proc because on the failure of a procedure
- % we don't need to prepare for execution to resume in this
- % procedure.
+:- type position_info.
+:- type branch_end_info.
-:- pred code_info__manufacture_failure_cont(bool, code_info, code_info).
-:- mode code_info__manufacture_failure_cont(in, in, out) is det.
+:- type branch_end == maybe(branch_end_info).
- % make_known_failure_cont(ResumeVars, ResumeLocs, IsNondet, Code):
- % Push a new failure continuation onto the stack.
+:- pred code_info__remember_position(position_info, code_info, code_info).
+:- mode code_info__remember_position(out, in, out) is det.
-:- pred code_info__make_known_failure_cont(set(var), resume_locs, bool,
+:- pred code_info__reset_to_position(position_info, code_info, code_info).
+:- mode code_info__reset_to_position(in, in, out) is det.
+
+:- pred code_info__generate_branch_end(store_map, branch_end, branch_end,
code_tree, code_info, code_info).
-:- mode code_info__make_known_failure_cont(in, in, in, out, in, out)
- is det.
+:- mode code_info__generate_branch_end(in, in, out, out, in, out) is det.
- % Generate some code to restore the current redoip, by looking
- % at the top of the failure continuation stack.
+:- pred code_info__after_all_branches(store_map, branch_end,
+ code_info, code_info).
+:- mode code_info__after_all_branches(in, in, in, out) is det.
-:- pred code_info__restore_failure_cont(code_tree, code_info, code_info).
-:- mode code_info__restore_failure_cont(out, in, out) is det.
+:- implementation.
- % XXX
+:- type position_info
+ ---> position_info(
+ code_info % The code_info at a given position
+ % in the code of the procedure.
+ ).
-:- pred code_info__failure_is_direct_branch(code_addr, code_info, code_info).
-:- mode code_info__failure_is_direct_branch(out, in, out) is semidet.
+:- type branch_end_info
+ ---> branch_end_info(
+ code_info % The code_info at the end of a branch.
+ ).
- % XXX
+code_info__remember_position(position_info(C), C, C).
-:- pred code_info__generate_failure(code_tree, code_info, code_info).
-:- mode code_info__generate_failure(out, in, out) is det.
+code_info__reset_to_position(position_info(PosCI), CurCI, NextCI) :-
+ % The static fields in PosCI and CurCI should be identical.
+ PosCI = code_info(_, _, _, _, _, _, _, _,
+ LA, LB, LC, LD, LE, LF, _, _, _, _, _, _ ),
+ CurCI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ _, _, _, _, _, _, PA, PB, PC, PD, PE, PF),
+ NextCI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
+ LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
- % XXX
+code_info__generate_branch_end(StoreMap, MaybeEnd0, MaybeEnd, Code) -->
+ code_info__get_exprn_info(Exprn0),
+ { map__to_assoc_list(StoreMap, VarLocs) },
+ { code_exprn__place_vars(VarLocs, Code, Exprn0, Exprn) },
+ code_info__set_exprn_info(Exprn),
+ =(EndCodeInfo1),
+ {
+ MaybeEnd0 = no,
+ EndCodeInfo = EndCodeInfo1
+ ;
+ MaybeEnd0 = yes(branch_end_info(EndCodeInfo0)),
-:- pred code_info__fail_if_rval_is_false(rval, code_tree,
- code_info, code_info).
-:- mode code_info__fail_if_rval_is_false(in, out, in, out) is det.
+ % Make sure the left context we leave the
+ % branched structure with is valid for all branches.
+ code_info__get_fail_info(FailInfo0, EndCodeInfo0, _),
+ code_info__get_fail_info(FailInfo1, EndCodeInfo1, _),
+ FailInfo0 = fail_info(_, ResumeKnown0, CurfrMaxfr0),
+ FailInfo1 = fail_info(R, ResumeKnown1, CurfrMaxfr1),
+ (
+ ResumeKnown0 = resume_point_known,
+ ResumeKnown1 = resume_point_known
+ ->
+ ResumeKnown = resume_point_known
+ ;
+ ResumeKnown = resume_point_unknown
+ ),
+ (
+ CurfrMaxfr0 = must_be_equal,
+ CurfrMaxfr1 = must_be_equal
+ ->
+ CurfrMaxfr = must_be_equal
+ ;
+ CurfrMaxfr = may_be_different
+ ),
+ FailInfo = fail_info(R, ResumeKnown, CurfrMaxfr),
+ code_info__set_fail_info(FailInfo, EndCodeInfo1, EndCodeInfo)
+ },
+ { MaybeEnd = yes(branch_end_info(EndCodeInfo)) }.
- % Set the topmost failure cont to `unknown' (e.g. after
- % a nondet call or after a disjunction).
+code_info__after_all_branches(StoreMap, MaybeEnd, CI0, CI) :-
+ (
+ MaybeEnd = yes(BranchEnd),
+ BranchEnd = branch_end_info(BranchEndCodeInfo),
+ code_info__reset_to_position(position_info(BranchEndCodeInfo),
+ CI0, CI1),
+ code_info__remake_with_store_map(StoreMap, CI1, CI)
+ ;
+ MaybeEnd = no,
+ error("no branches in branched control structure")
+ ).
-:- pred code_info__unset_failure_cont(code_tree, code_info, code_info).
-:- mode code_info__unset_failure_cont(out, in, out) is det.
+ % code_info__remake_with_store_map throws away the exprn_info data
+ % structure, forgetting the current locations of all variables,
+ % and rebuilds it from scratch based on the given store map.
+ % The new exprn_info will know about only the variables present
+ % in the store map, and will believe they are where the store map
+ % says they are.
- % Flush the variables needed for any current resumption point
- % to their stack slots.
+:- pred code_info__remake_with_store_map(store_map, code_info, code_info).
+:- mode code_info__remake_with_store_map(in, in, out) is det.
-:- pred code_info__flush_resume_vars_to_stack(code_tree, code_info, code_info).
-:- mode code_info__flush_resume_vars_to_stack(out, in, out) is det.
+code_info__remake_with_store_map(StoreMap) -->
+ { map__to_assoc_list(StoreMap, VarLvals) },
+ { code_info__fixup_lvallist(VarLvals, VarRvals) },
+ code_info__get_exprn_info(Exprn0),
+ { code_exprn__reinit_state(VarRvals, Exprn0, Exprn) },
+ code_info__set_exprn_info(Exprn).
- % XXX
+:- pred code_info__fixup_lvallist(assoc_list(var, lval), assoc_list(var, rval)).
+:- mode code_info__fixup_lvallist(in, out) is det.
-:- pred code_info__may_use_nondet_tailcall(bool, code_info, code_info).
-:- mode code_info__may_use_nondet_tailcall(out, in, out) is det.
+code_info__fixup_lvallist([], []).
+code_info__fixup_lvallist([V - L | Ls], [V - lval(L) | Rs]) :-
+ code_info__fixup_lvallist(Ls, Rs).
- % do_soft_cut(NondetFrameLvalAddress, SoftCutCode, SoftCutContCode)
- % takes the lval where the address of the
- % failure frame is stored, and it returns code to
- % prune away the topmost choice point from that frame,
- % typically by setting the redoip of that frame to do_fail.
- % Note that the frame need not be the topmost frame -- a soft cut
- % can prune away a single choice point from the middle.
- % do_soft_cut also returns some additional code; in the case of
- % trailing, the redoip will be set to point to that additional code,
- % not to do_fail; the additional code will do a `discard_ticket'
- % before branching to the usual failure continuation (e.g. do_fail).
-
-:- pred code_info__do_soft_cut(lval, code_tree, code_tree,
- code_info, code_info).
-:- mode code_info__do_soft_cut(in, out, out, in, out) is det.
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
- % `generate_semi_pre_commit' and `generate_semi_commit' should be
- % called before and after generating the code for the nondet goal
- % being cut across. If the goal succeeds, the `commit' will cut
- % any choice points generated in the goal.
- %
- % `generate_semi_pre_commit' returns a label (a failure cont label)
- % and a tuple of stack slots; both of these should be passed to
- % `generate_semi_commit'.
+ % Submodule for the handling of failure continuations.
-:- pred code_info__generate_semi_pre_commit(label, commit_slots, code_tree,
- code_info, code_info).
-:- mode code_info__generate_semi_pre_commit(out, out, out, in, out) is det.
+:- interface.
-:- pred code_info__generate_semi_commit(label, commit_slots, code_tree,
- code_info, code_info).
-:- mode code_info__generate_semi_commit(in, in, out, in, out) is det.
+:- type resume_map.
- % `generate_det_pre_commit' and `generate_det_commit' should be
- % called before and after generating the code for the multi goal
- % being cut across. If the goal succeeds, the `commit' will cut
- % any choice points generated in the goal.
- %
- % `generate_det_pre_commit' returns a tuple of stack slots, which
- % should be passed to `generate_det_commit'.
+:- type resume_point_info.
-:- pred code_info__generate_det_pre_commit(commit_slots, code_tree,
- code_info, code_info).
-:- mode code_info__generate_det_pre_commit(out, out, in, out) is det.
+:- type disj_hijack_info.
-:- pred code_info__generate_det_commit(commit_slots, code_tree,
- code_info, code_info).
-:- mode code_info__generate_det_commit(in, out, in, out) is det.
+ % Save the values of any stack slots we may hijack,
+ % and if necessary, set the redofr slot of the top frame
+ % to point to this frame.
-:- type commit_slots
- ---> commit_slots(
- lval, % curfr
- lval, % maxfr
- lval, % redoip
- maybe(pair(lval, lval)) % ticket counter, trail pointer
- ).
+:- pred code_info__prepare_for_disj_hijack(code_model::in,
+ disj_hijack_info::out, code_tree::out,
+ code_info::in, code_info::out) is det.
-%---------------------------------------------------------------------------%
+:- pred code_info__undo_disj_hijack(disj_hijack_info::in,
+ code_tree::out, code_info::in, code_info::out) is det.
-:- implementation.
+:- type ite_hijack_info.
-:- type fail_stack == stack(failure_cont).
+:- pred code_info__prepare_for_ite_hijack(code_model::in,
+ ite_hijack_info::out, code_tree::out,
+ code_info::in, code_info::out) is det.
-:- type failure_cont
- ---> failure_cont(
- failure_cont_info,
- resume_maps
- ).
+:- pred code_info__maybe_push_temp_frame(code_model::in, bool::in,
+ ite_hijack_info::in, lval::out, code_tree::out,
+ code_info::in, code_info::out) is det.
-:- type failure_cont_info
- ---> semidet
- ; nondet(
- is_known, % Says whether on failure we can branch
- % directly to one of the labels in
- % the resume_maps, or if we must
- % instead execute a redo.
-
- maybe(label) % The maybe(label) is yes if we have
- % created a temporary frame and we
- % must restore curfr after a redo().
- ).
+:- pred code_info__ite_enter_then(ite_hijack_info::in, lval::in,
+ code_tree::out, code_tree::out, code_info::in, code_info::out) is det.
-:- type is_known ---> known ; unknown.
+:- type simple_neg_info.
-:- type resume_map == map(var, set(rval)).
+:- pred code_info__enter_simple_neg(set(var)::in, hlds_goal_info::in,
+ simple_neg_info::out, code_info::in, code_info::out) is det.
-:- type resume_maps
- ---> orig_only(resume_map, code_addr)
- ; stack_only(resume_map, code_addr)
- ; orig_and_stack(resume_map, code_addr, resume_map, code_addr)
- ; stack_and_orig(resume_map, code_addr, resume_map, code_addr).
+:- pred code_info__leave_simple_neg(hlds_goal_info::in, simple_neg_info::in,
+ code_info::in, code_info::out) is det.
-:- pred code_info__fail_cont_is_known(failure_cont_info).
-:- mode code_info__fail_cont_is_known(in) is semidet.
+ % Put the given resume point into effect, by pushing it on to
+ % the resume point stack, and if necessary overriding the redoip
+ % of the top frame.
-code_info__fail_cont_is_known(FailContInfo) :-
- FailContInfo \= nondet(unknown, _).
+:- pred code_info__effect_resume_point(resume_point_info::in, code_model::in,
+ code_tree::out, code_info::in, code_info::out) is det.
-:- pred code_info__fail_cont_is_unknown(failure_cont_info).
-:- mode code_info__fail_cont_is_unknown(in) is semidet.
+:- pred code_info__top_resume_point(resume_point_info::out,
+ code_info::in, code_info::out) is det.
-code_info__fail_cont_is_unknown(FailContInfo) :-
- FailContInfo = nondet(unknown, _).
+ % We have just left a disjunction; we don't know what address
+ % the following code will need to backtrack to.
-:- pred code_info__have_temp_frame(fail_stack).
-:- mode code_info__have_temp_frame(in) is semidet.
+:- pred code_info__set_resume_point_to_unknown(code_info::in, code_info::out)
+ is det.
- % have_temp_frame should succeed iff we have created
- % a temp frame on the nondet stack. It traverses
- % the entire failure continuation stack, looking for
- % any failure continuations with the temp frame maybe(label)
- % set to yes(_).
+ % We have just returned a model_non call; we don't know what address
+ % the following code will need to backtrack to, and there may now
+ % be nondet frames on top of ours that do not have their redofr slots
+ % pointing to our frame.
-code_info__have_temp_frame(FailStack0) :-
- stack__pop(FailStack0, FailContInfo, FailStack1),
- (
- FailContInfo = failure_cont(nondet(_, yes(_)), _)
- ;
- code_info__have_temp_frame(FailStack1)
- ).
+:- pred code_info__set_resume_point_and_frame_to_unknown(code_info::in,
+ code_info::out) is det.
-%---------------------------------------------------------------------------%
+:- pred code_info__generate_failure(code_tree::out,
+ code_info::in, code_info::out) is det.
-code_info__manufacture_failure_cont(IsNondet) -->
- { map__init(Empty) },
- (
- { IsNondet = no },
- code_info__get_next_label(ContLab1),
- { Address1 = label(ContLab1) },
- { ResumeMap = stack_only(Empty, Address1) },
- { ContInfo = semidet }
- ;
- { IsNondet = yes },
- { Address1 = do_fail },
- { ResumeMap = stack_only(Empty, Address1) },
- { ContInfo = nondet(known, no) }
- ),
- code_info__push_failure_cont(failure_cont(ContInfo, ResumeMap)).
+:- pred code_info__fail_if_rval_is_false(rval::in, code_tree::out,
+ code_info::in, code_info::out) is det.
-%---------------------------------------------------------------------------%
+:- pred code_info__failure_is_direct_branch(code_addr::out,
+ code_info::in, code_info::out) is semidet.
-code_info__make_known_failure_cont(ResumeVars, ResumeLocs, IsNondet,
- ModContCode) -->
- code_info__get_next_label(OrigLabel),
- code_info__get_next_label(StackLabel),
- { OrigAddr = label(OrigLabel) },
- { StackAddr = label(StackLabel) },
- (
- % In semidet continuations we don't use the redoip
- % of the top stack frame.
+:- pred code_info__may_use_nondet_tailcall(bool::out,
+ code_info::in, code_info::out) is det.
- { IsNondet = no },
- { TempFrameCode = empty },
- { FailContInfo = semidet }
- ;
- % In nondet continuations we may use the redoip
- % of the top stack frame. Therefore we must ensure
- % that this redoip is free for use, creating our own
- % frame if necessary.
+ % Materialize the given variables into registers or stack slots.
- { IsNondet = yes },
- code_info__top_failure_cont(FailureCont),
- { FailureCont = failure_cont(OrigInfo, _) },
- (
- { code_info__fail_cont_is_unknown(OrigInfo) }
- ->
- %
- % If the failure continuation is unknown,
- % then we need to create a new temporary frame
- % so that we can make it known
- %
- code_info__get_next_label(RedoLabel),
- { MaybeRedoLabel = yes(RedoLabel) },
- { RedoAddr = label(RedoLabel) },
- % this code could be better
- % (mkframe is a bit of a sledge hammer)
- { TempFrameCode = node([
- mkframe("temp frame", 1, no, RedoAddr)
- - "create a temporary frame",
- assign(curfr, lval(succfr(lval(maxfr))))
- - "restore curfr after mkframe"
- ]) }
- ;
- %
- % The failure continuation is known.
- % But did we create a temp frame?
- %
- code_info__get_fail_stack(FailStack),
- (
- { code_info__have_temp_frame(FailStack) }
- ->
- %
- % If we created a temp frame, then
- % we will need to restore curfr on redo,
- % so we set the failure continuation to
- % the RedoAddr rather than the usual
- % StackAddr. (generate_failure_cont will
- % generate code for it that restores curfr.)
- %
- code_info__get_next_label(RedoLabel),
- { MaybeRedoLabel = yes(RedoLabel) },
- { RedoAddr = label(RedoLabel) },
- { TempFrameCode = node([
- assign(redoip(lval(maxfr)),
- const(code_addr_const(RedoAddr)))
- - "Set failure continuation on temp frame"
- ]) }
- ;
- { MaybeRedoLabel = no },
- { TempFrameCode = node([
- assign(redoip(lval(maxfr)),
- const(code_addr_const(StackAddr)))
- - "Set failure continuation"
- ]) }
- )
- ),
- { FailContInfo = nondet(known, MaybeRedoLabel) }
- ),
- { set__to_sorted_list(ResumeVars, VarList) },
- (
- { ResumeLocs = orig_only },
- code_info__produce_resume_vars(VarList, OrigMap, OrigCode),
- { ResumeMaps = orig_only(OrigMap, OrigAddr) }
- ;
- { ResumeLocs = stack_only },
- code_info__produce_resume_vars(VarList, _OrigMap, OrigCode),
- code_info__get_stack_slots(StackSlots),
- { map__select(StackSlots, ResumeVars, StackMap0) },
- { map__to_assoc_list(StackMap0, StackList0) },
- { code_info__tweak_stacklist(StackList0, StackList) },
- { map__from_assoc_list(StackList, StackMap) },
- { ResumeMaps = stack_only(StackMap, StackAddr) }
- ;
- { ResumeLocs = orig_and_stack },
- code_info__produce_resume_vars(VarList, OrigMap, OrigCode),
- code_info__get_stack_slots(StackSlots),
- { map__select(StackSlots, ResumeVars, StackMap0) },
- { map__to_assoc_list(StackMap0, StackList0) },
- { code_info__tweak_stacklist(StackList0, StackList) },
- { map__from_assoc_list(StackList, StackMap) },
- { ResumeMaps = orig_and_stack(OrigMap, OrigAddr,
- StackMap, StackAddr) }
- ;
- { ResumeLocs = stack_and_orig },
- code_info__produce_resume_vars(VarList, OrigMap, OrigCode),
- code_info__get_stack_slots(StackSlots),
- { map__select(StackSlots, ResumeVars, StackMap0) },
- { map__to_assoc_list(StackMap0, StackList0) },
- { code_info__tweak_stacklist(StackList0, StackList) },
- { map__from_assoc_list(StackList, StackMap) },
- { ResumeMaps = stack_and_orig(StackMap, StackAddr,
- OrigMap, OrigAddr) }
- ),
- code_info__push_failure_cont(failure_cont(FailContInfo, ResumeMaps)),
- { ModContCode = tree(OrigCode, TempFrameCode) }.
+:- pred code_info__produce_vars(set(var)::in, resume_map::out,
+ code_tree::out, code_info::in, code_info::out) is det.
-:- pred code_info__produce_resume_vars(list(var), map(var, set(rval)),
- code_tree, code_info, code_info).
-:- mode code_info__produce_resume_vars(in, out, out, in, out) is det.
+ % Put the variables needed in enclosing failure continuations
+ % into their stack slots.
-code_info__produce_resume_vars([], Map, empty) -->
- { map__init(Map) }.
-code_info__produce_resume_vars([V | Vs], Map, Code) -->
- code_info__produce_resume_vars(Vs, Map0, Code0),
- code_info__produce_variable_in_reg_or_stack(V, Code1, Rval),
- { set__singleton_set(Rvals, Rval) },
- { map__set(Map0, V, Rvals, Map) },
- { Code = tree(Code0, Code1) }.
+:- pred code_info__flush_resume_vars_to_stack(code_tree::out,
+ code_info::in, code_info::out) is det.
-:- pred code_info__tweak_stacklist(assoc_list(var, lval),
- assoc_list(var, set(rval))).
-:- mode code_info__tweak_stacklist(in, out) is det.
+ % Set up the resume_point_info structure.
-code_info__tweak_stacklist([], []).
-code_info__tweak_stacklist([V - L | Rest0], [V - Rs | Rest]) :-
- set__singleton_set(Rs, lval(L)),
- code_info__tweak_stacklist(Rest0, Rest).
+:- pred code_info__make_resume_point(set(var)::in, resume_locs::in,
+ resume_map::in, resume_point_info::out, code_info::in, code_info::out)
+ is det.
-%---------------------------------------------------------------------------%
+ % Generate the code for a resume point.
-% :- pred code_info__modify_failure_cont(code_tree, code_info, code_info).
-% :- mode code_info__modify_failure_cont(out, in, out) is det.
-%
-% code_info__modify_failure_cont(ModifyCode) -->
-% code_info__top_failure_cont(FailureCont),
-% { FailureCont = failure_cont(OldCont, MaybeRedo0, FailureMap) },
-% code_info__generate_failure_cont(FailureCont, FailureCode),
-% code_info__pop_failure_cont,
-% code_info__get_next_label(NewRegCont),
-% code_info__get_next_label(NewStackCont),
-% (
-% { OldCont = unknown ; OldCont = known(yes) }
-% ->
-% { NewCont = known(yes) },
-% ( { MaybeRedo0 = yes(_OldRedo) } ->
-% code_info__get_next_label(NewRedoCont),
-% { MaybeRedo = yes(NewRedoCont) }
-% ;
-% { NewRedoCont = NewStackCont },
-% { MaybeRedo = no }
-% ),
-% { ResetCode = node([
-% assign(redoip(lval(maxfr)),
-% const(code_addr_const(label(NewRedoCont)))) -
-% "modify failure cont"
-% ]) }
-% ;
-% { error("code_info__modify_failure_cont: semidet context") }
-% % { NewCont = known(no) },
-% % { ResetCode = empty },
-% % { MaybeRedo = no }
-% ),
-% (
-% { FailureMap = [RegMap - _RegCont, StackMap - _StackCont] }
-% ->
-% code_info__push_failure_cont(failure_cont(NewCont, MaybeRedo,
-% [RegMap - label(NewRegCont),
-% StackMap - label(NewStackCont)]))
-% ;
-% { error("code_info__modify_failure_cont: bad failure map.") }
-% ),
-% { ModifyCode = tree(FailureCode, ResetCode) }.
+:- pred code_info__generate_resume_point(resume_point_info::in,
+ code_tree::out, code_info::in, code_info::out) is det.
-%---------------------------------------------------------------------------%
+:- pred code_info__resume_point_vars(resume_point_info::in, list(var)::out)
+ is det.
-code_info__restore_failure_cont(Code) -->
- code_info__top_failure_cont(CurFailureCont),
- { CurFailureCont = failure_cont(CurContInfo, _FailureMap) },
- code_info__generate_failure_cont(CurFailureCont, FailureCode),
- code_info__pop_failure_cont,
- % Fixup the redoip of the top frame if necessary
- (
- { CurContInfo = semidet },
- { ResetCode = empty }
- ;
- { CurContInfo = nondet(_, _) },
- code_info__top_failure_cont(EnclosingFailureCont),
- { EnclosingFailureCont = failure_cont(EnclosingContInfo, _) },
- {
- EnclosingContInfo = semidet,
- ResetCode = empty
- ;
- EnclosingContInfo = nondet(unknown, _),
- ResetCode = node([
- assign(redoip(lval(maxfr)),
- const(code_addr_const(do_fail))) -
- "restore failure cont"
- ])
- ;
- EnclosingContInfo = nondet(known, _),
- code_info__find_first_resume_label(
- EnclosingFailureCont, RedoAddress),
- ResetCode = node([
- assign(redoip(lval(maxfr)),
- const(code_addr_const(RedoAddress)))
- - "restore known failure cont"
- ])
- }
- ),
- { Code = tree(FailureCode, ResetCode) }.
+:- pred code_info__resume_point_stack_addr(resume_point_info::in,
+ code_addr::out) is det.
+
+ % `generate_det_pre_commit' and `generate_det_commit' should be
+ % called before and after generating the code for the multi goal
+ % being cut across. If the goal succeeds, the `commit' will cut
+ % any choice points generated in the goal.
+
+:- type det_commit_info.
+
+:- pred code_info__generate_det_pre_commit(det_commit_info::out,
+ code_tree::out, code_info::in, code_info::out) is det.
+
+:- pred code_info__generate_det_commit(det_commit_info::in,
+ code_tree::out, code_info::in, code_info::out) is det.
+
+ % `generate_semi_pre_commit' and `generate_semi_commit' should be
+ % called before and after generating the code for the nondet goal
+ % being cut across. If the goal succeeds, the `commit' will cut
+ % any choice points generated in the goal.
+
+:- type semi_commit_info.
+
+:- pred code_info__generate_semi_pre_commit(semi_commit_info::out,
+ code_tree::out, code_info::in, code_info::out) is det.
+
+:- pred code_info__generate_semi_commit(semi_commit_info::in,
+ code_tree::out, code_info::in, code_info::out) is det.
%---------------------------------------------------------------------------%
- % In establishing this resumption point, we may have pushed
- % a temporary frame onto the nondet stack. If we have done so,
- % we will have recorded this fact by setting the second argument
- % of the top failure continuation to yes, with the argument of
- % the yes giving the name of the label whose address was put
- % into the redoip slot of that frame.
- %
- % When control arrives at that label, curfr will point to the
- % temporary frame. However, the variables needed by the code
- % at the resumption point are in the main nondet frame of the
- % procedure. Since this was the current frame when we created
- % the temporary frame, we can find it by following the succfr
- % link in the temporary frame.
- %
- % The code we generate in general is
- %
- % label(RedoLabel)
- % <reset curfr>
- % label(StackLabel)
- % <assume variables are where StackMap says they are>
- % <copy variables to their locations according to OrigMap>
- % label(OrigLabel)
- % <assume variables are where OrigMap says they are>
- %
- % If, in establishing this resumption point, we did not create
- % a temporary frame, then curfr will be OK when code to the right
- % does a fail(), and hence the first label and the resetting of
- % the curfr register can be omitted.
- %
- % Failures at different points may cause control to arrive at
- % the resumption point via any one of these each labels.
- % The last line above is necessary since it may arrive at OrigLabel
- % without going through StackLabel first.
- %
- % The first two lines above are generated in this predicate;
- % the others are generated in code_info__generate_resume_setup.
- % It may not generate some of these other lines if it knows that
- % they won't be needed.
-
-:- pred code_info__generate_failure_cont(failure_cont, code_tree,
- code_info, code_info).
-:- mode code_info__generate_failure_cont(in, out, in, out) is det.
-
-code_info__generate_failure_cont(FailureCont, Code) -->
- { FailureCont = failure_cont(ContInfo, ResumeMap) },
-
- % Did we create a temp nondet frame for this continuation?
- % If not, then curfr will be right when we arrive here.
- % If yes, it will be wrong, pointing to the temp frame,
- % so we must restore curfr before continuing.
- {
- ContInfo = nondet(_, MaybeRedoLabel),
- MaybeRedoLabel = yes(RedoLabel)
- ->
- FixCurFrCode = node([
- label(RedoLabel) -
- "redo entry point",
- assign(curfr, lval(succfr(lval(maxfr)))) -
- "restore curfr"
- ]),
+:- implementation.
+
+:- type resume_point_known ---> resume_point_known
+ ; resume_point_unknown.
+
+:- type curfr_vs_maxfr ---> must_be_equal
+ ; may_be_different.
+
+:- type resume_map == map(var, set(rval)).
+
+:- type resume_point_info
+ ---> orig_only(resume_map, code_addr)
+ ; stack_only(resume_map, code_addr)
+ ; orig_and_stack(resume_map, code_addr, resume_map, code_addr)
+ ; stack_and_orig(resume_map, code_addr, resume_map, code_addr).
+
+:- type fail_info
+ ---> fail_info(
+ stack(resume_point_info),
+ resume_point_known,
+ curfr_vs_maxfr
+ ).
+
+:- type disj_hijack_info
+ ---> disj_no_hijack
+ ; disj_quarter_hijack
+ ; disj_half_hijack(
+ lval % the stack slot in which we saved
+ % the value of the hijacked redoip
+ )
+ ; disj_full_hijack(
+ lval, % the stack slot in which we saved
+ % the value of the hijacked redoip
+ lval % the stack slot in which we saved
+ % the value of the hijacked redofr
+ ).
+
+:- type ite_hijack_info
+ ---> ite_no_hijack(
+ resume_point_known
+ )
+ ; ite_quarter_hijack(
+ resume_point_known
+ )
+ ; ite_half_hijack(
+ resume_point_known,
+ lval % the stack slot in which we saved
+ % the value of the hijacked redoip
+ )
+ ; ite_full_hijack(
+ resume_point_known,
+ lval, % the stack slot in which we saved
+ % the value of the hijacked redoip
+ lval, % the stack slot in which we saved
+ % the value of the hijacked redofr
+ lval % the stack slot in which we saved
+ % the value of maxfr
+ ).
+
+:- type simple_neg_info == fail_info.
+
+code_info__prepare_for_disj_hijack(CodeModel, HijackInfo, Code) -->
+ ( { CodeModel = model_non } ->
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr) },
(
- ( ResumeMap = orig_only(_, _)
- ; ResumeMap = orig_and_stack(_, _, _, _)
- )
- ->
- error("redo entry before an orig resume point")
+ { CurfrMaxfr = may_be_different },
+ code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
+ RedoipSlot),
+ code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
+ RedofrSlot),
+ { HijackInfo = disj_full_hijack(RedoipSlot,
+ RedofrSlot) },
+ { Code = node([
+ assign(RedoipSlot, lval(redoip(lval(maxfr))))
+ - "prepare for full disj hijack",
+ assign(RedofrSlot, lval(redofr(lval(maxfr))))
+ - "prepare for full disj hijack",
+ assign(redofr(lval(maxfr)), lval(curfr))
+ - "prepare for full disj hijack"
+ ]) }
;
- true
+ { CurfrMaxfr = must_be_equal },
+ (
+ { ResumeKnown = resume_point_unknown },
+ code_info__acquire_temp_slot(
+ lval(redoip(lval(curfr))), RedoipSlot),
+ { HijackInfo = disj_half_hijack(RedoipSlot) },
+ { Code = node([
+ assign(RedoipSlot,
+ lval(redoip(lval(curfr))))
+ - "prepare for half disj hijack"
+ ]) }
+ ;
+ { ResumeKnown = resume_point_known },
+ { HijackInfo = disj_quarter_hijack },
+ { Code = empty }
+ )
)
;
- FixCurFrCode = empty
- },
- code_info__generate_resume_setup(ResumeMap, ResumeCode),
- { Code = tree(FixCurFrCode, ResumeCode) }.
-
-:- pred code_info__generate_resume_setup(resume_maps, code_tree,
- code_info, code_info).
-:- mode code_info__generate_resume_setup(in, out, in, out) is det.
+ { HijackInfo = disj_no_hijack },
+ { Code = empty }
+ ).
-code_info__generate_resume_setup(ResumeMaps, Code) -->
+code_info__undo_disj_hijack(HijackInfo, Code) -->
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr) },
(
- { ResumeMaps = orig_only(Map1, Addr1) },
- { extract_label_from_code_addr(Addr1, Label1) },
+ { HijackInfo = disj_full_hijack(RedoipSlot, RedofrSlot) },
+ { require(unify(CurfrMaxfr, may_be_different),
+ "maxfr same as curfr in disj_full_hijack") },
{ Code = node([
- label(Label1) -
- "orig only failure continuation"
- ]) },
- code_info__set_var_locations(Map1)
+ assign(redoip(lval(maxfr)), lval(RedoipSlot))
+ - "restore redoip for full disj hijack",
+ assign(redofr(lval(maxfr)), lval(RedofrSlot))
+ - "restore redofr for full disj hijack"
+ ]) }
;
- { ResumeMaps = stack_only(Map1, Addr1) },
- { extract_label_from_code_addr(Addr1, Label1) },
+ { HijackInfo = disj_half_hijack(RedoipSlot) },
+ { require(unify(ResumeKnown, resume_point_unknown),
+ "resume point known in disj_half_hijack") },
+ { require(unify(CurfrMaxfr, must_be_equal),
+ "maxfr may be different from curfr in disj_half_hijack") },
{ Code = node([
- label(Label1) -
- "stack only failure continuation"
- ]) },
- code_info__set_var_locations(Map1)
+ assign(redoip(lval(curfr)), lval(RedoipSlot))
+ - "restore redoip for half disj hijack"
+ ]) }
;
- { ResumeMaps = stack_and_orig(Map1, Addr1, Map2, Addr2) },
- { extract_label_from_code_addr(Addr1, Label1) },
- { extract_label_from_code_addr(Addr2, Label2) },
- { Label1Code = node([
- label(Label1) -
- "stack failure continuation before orig"
- ]) },
- code_info__set_var_locations(Map1),
- { map__to_assoc_list(Map2, AssocList2) },
- code_info__place_resume_vars(AssocList2, PlaceCode),
- { Label2Code = node([
- label(Label2) -
- "orig failure continuation after stack"
- ]) },
- code_info__set_var_locations(Map2),
- { Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+ { HijackInfo = disj_quarter_hijack },
+ { require(unify(ResumeKnown, resume_point_known),
+ "resume point not known in disj_quarter_hijack") },
+ { require(unify(CurfrMaxfr, must_be_equal),
+ "maxfr may be different from curfr in disj_quarter_hijack") },
+ { stack__top_det(ResumePoints, ResumePoint) },
+ { code_info__pick_stack_resume_point(ResumePoint,
+ _, StackLabel) },
+ { LabelConst = const(code_addr_const(StackLabel)) },
+ { Code = node([
+ assign(redoip(lval(curfr)), LabelConst)
+ - "restore redoip for quarter disj hijack"
+ ]) }
;
- { ResumeMaps = orig_and_stack(Map1, Addr1, Map2, Addr2) },
- { extract_label_from_code_addr(Addr1, Label1) },
- { extract_label_from_code_addr(Addr2, Label2) },
- { Label1Code = node([
- label(Label1) -
- "orig failure continuation before stack"
- ]) },
- code_info__set_var_locations(Map1),
- { map__to_assoc_list(Map2, AssocList2) },
- code_info__place_resume_vars(AssocList2, PlaceCode),
- { Label2Code = node([
- label(Label2) -
- "stack failure continuation after orig"
- ]) },
- code_info__set_var_locations(Map2),
- { Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+ { HijackInfo = disj_no_hijack },
+ { Code = empty }
).
-:- pred extract_label_from_code_addr(code_addr, label).
-:- mode extract_label_from_code_addr(in, out) is det.
-
-extract_label_from_code_addr(CodeAddr, Label) :-
- ( CodeAddr = label(Label0) ->
- Label = Label0
+code_info__prepare_for_ite_hijack(EffCodeModel, HijackInfo, Code) -->
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(_ResumePoints, ResumeKnown, CurfrMaxfr) },
+ ( { EffCodeModel = model_non } ->
+ (
+ { CurfrMaxfr = may_be_different },
+ code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
+ RedoipSlot),
+ code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
+ RedofrSlot),
+ code_info__acquire_temp_slot(lval(maxfr),
+ MaxfrSlot),
+ { HijackInfo = ite_full_hijack(ResumeKnown,
+ RedoipSlot, RedofrSlot, MaxfrSlot) },
+ { Code = node([
+ assign(MaxfrSlot, lval(maxfr))
+ - "prepare for full ite hijack",
+ assign(RedoipSlot, lval(redoip(lval(maxfr))))
+ - "prepare for full ite hijack",
+ assign(RedofrSlot, lval(redofr(lval(maxfr))))
+ - "prepare for full ite hijack",
+ assign(redofr(lval(maxfr)), lval(curfr))
+ - "prepare for full ite hijack"
+ ]) }
+ ;
+ { CurfrMaxfr = must_be_equal },
+ (
+ { ResumeKnown = resume_point_unknown },
+ code_info__acquire_temp_slot(
+ lval(redoip(lval(curfr))), RedoipSlot),
+ { HijackInfo = ite_half_hijack(ResumeKnown,
+ RedoipSlot) },
+ { Code = node([
+ assign(RedoipSlot,
+ lval(redoip(lval(curfr))))
+ - "prepare for half ite hijack"
+ ]) }
+ ;
+ { ResumeKnown = resume_point_known },
+ { HijackInfo = ite_quarter_hijack(
+ ResumeKnown) },
+ { Code = empty }
+ )
+ )
;
- error("code_info__generate_resume_setup: non-label!")
+ { HijackInfo = ite_no_hijack(ResumeKnown) },
+ { Code = empty }
).
-:- pred code_info__place_resume_vars(assoc_list(var, set(rval)), code_tree,
- code_info, code_info).
-:- mode code_info__place_resume_vars(in, out, in, out) is det.
-
-code_info__place_resume_vars([], empty) --> [].
-code_info__place_resume_vars([Var - TargetSet | Rest], Code) -->
- { set__to_sorted_list(TargetSet, Targets) },
- code_info__place_resume_var(Var, Targets, FirstCode),
- { Code = tree(FirstCode, RestCode) },
- code_info__place_resume_vars(Rest, RestCode).
-
-:- pred code_info__place_resume_var(var, list(rval), code_tree,
- code_info, code_info).
-:- mode code_info__place_resume_var(in, in, out, in, out) is det.
-
-code_info__place_resume_var(_Var, [], empty) --> [].
-code_info__place_resume_var(Var, [Target | Targets], Code) -->
- ( { Target = lval(TargetLval) } ->
- code_info__place_var(Var, TargetLval, FirstCode)
+code_info__maybe_push_temp_frame(EffCodeModel, CanHijack, HijackInfo,
+ CutFrame, Code) -->
+ ( { EffCodeModel = model_non } ->
+ ( { HijackInfo = ite_full_hijack(_, _, _, MaxfrSlot0) } ->
+ { CutFrame = MaxfrSlot0 }
+ ;
+ { CutFrame = curfr }
+ ),
+ (
+ { CanHijack = yes },
+ { Code = node([
+ mkframe(temp_frame, do_fail)
+ - "protect slots hijacked by ite"
+ ]) },
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(ResumePoints, ResumeKnown,
+ _) },
+ { FailInfo = fail_info(ResumePoints, ResumeKnown,
+ may_be_different) },
+ code_info__set_fail_info(FailInfo)
+ ;
+ { CanHijack = no },
+ { Code = empty }
+ )
;
- { error("code_info__place_resume_var: not lval") }
- ),
- { Code = tree(FirstCode, RestCode) },
- code_info__place_resume_var(Var, Targets, RestCode).
+ { CutFrame = maxfr },
+ { Code = empty }
+ ).
- % Reset the code generator's database of what is where.
- % Remember that the variables in the map are available in their
- % associated rvals; forget about all other variables.
+code_info__ite_enter_then(HijackInfo, CutFrame, ThenCode, ElseCode) -->
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(ResumePoints0, ResumeKnown0, CurfrMaxfr) },
+ { stack__pop_det(ResumePoints0, _, ResumePoints) },
+ {
+ HijackInfo = ite_full_hijack(ResumeKnown1,
+ RedoipSlot, RedofrSlot, MaxfrSlot),
+ ThenCode = node([
+ assign(redoip(lval(MaxfrSlot)), lval(RedoipSlot))
+ - "restore redoip for full ite hijack",
+ assign(redofr(lval(MaxfrSlot)), lval(RedofrSlot))
+ - "restore redofr for full ite hijack"
+ ]),
+ ElseCode = node([
+ assign(redoip(lval(maxfr)), lval(RedoipSlot))
+ - "restore redoip for full ite hijack",
+ assign(redofr(lval(maxfr)), lval(RedofrSlot))
+ - "restore redofr for full ite hijack"
+ ])
+ ;
+ HijackInfo = ite_half_hijack(ResumeKnown1, RedoipSlot),
+ ThenCode = node([
+ assign(redoip(lval(CutFrame)), lval(RedoipSlot))
+ - "restore redoip for half ite hijack"
+ ]),
+ ElseCode = ThenCode
+ ;
+ HijackInfo = ite_quarter_hijack(ResumeKnown1),
+ stack__top_det(ResumePoints, ResumePoint),
+ (
+ code_info__maybe_pick_stack_resume_point(ResumePoint,
+ _, StackLabel)
+ ->
+ LabelConst = const(code_addr_const(StackLabel)),
+ ThenCode = node([
+ assign(redoip(lval(CutFrame)), LabelConst) -
+ "restore redoip for quarter ite hijack"
+ ])
+ ;
+ ThenCode = empty
+ ),
+ ElseCode = ThenCode
+ ;
+ HijackInfo = ite_no_hijack(ResumeKnown1),
+ ThenCode = empty,
+ ElseCode = ThenCode
+ },
+ {
+ ResumeKnown0 = resume_point_known,
+ ResumeKnown1 = resume_point_known
+ ->
+ ResumeKnown = resume_point_known
+ ;
+ ResumeKnown = resume_point_unknown
+ },
+ { FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr) },
+ code_info__set_fail_info(FailInfo).
-:- pred code_info__set_var_locations(map(var, set(rval)), code_info, code_info).
-:- mode code_info__set_var_locations(in, in, out) is det.
+code_info__enter_simple_neg(ResumeVars, GoalInfo, FailInfo0) -->
+ code_info__get_fail_info(FailInfo0),
+ % The only reason why we push a resume point at all
+ % is to protect the variables in ResumeVars from becoming
+ % unknown; by including them in the domain of the resume point,
+ % we guarantee that the will become zombies instead of unknown
+ % if they die in the pre- or post-goal updates.
+ % Therefore the only part of ResumePoint that matters
+ % is the set of variables in the resume map; the other
+ % parts of ResumePoint (the locations, the code address)
+ % will not be referenced.
+ { set__to_sorted_list(ResumeVars, ResumeVarList) },
+ { map__init(ResumeMap0) },
+ { code_info__make_fake_resume_map(ResumeVarList,
+ ResumeMap0, ResumeMap) },
+ { ResumePoint = orig_only(ResumeMap, do_redo) },
+ code_info__effect_resume_point(ResumePoint, model_semi, Code),
+ { require(unify(Code, empty), "nonempty code for simple neg") },
+ code_info__pre_goal_update(GoalInfo, yes).
+
+code_info__leave_simple_neg(GoalInfo, FailInfo) -->
+ code_info__post_goal_update(GoalInfo),
+ code_info__set_fail_info(FailInfo).
+
+:- pred code_info__make_fake_resume_map(list(var)::in,
+ map(var, set(rval))::in, map(var, set(rval))::out) is det.
+
+code_info__make_fake_resume_map([], ResumeMap, ResumeMap).
+code_info__make_fake_resume_map([Var | Vars], ResumeMap0, ResumeMap) :-
+ % a visibly fake location
+ set__singleton_set(Locns, lval(reg(r, -1))),
+ map__det_insert(ResumeMap0, Var, Locns, ResumeMap1),
+ code_info__make_fake_resume_map(Vars, ResumeMap1, ResumeMap).
-code_info__set_var_locations(Map) -->
- { map__to_assoc_list(Map, List0) },
- { code_info__flatten_varlval_list(List0, List) },
- code_info__get_exprn_info(Exprn0),
- { code_exprn__reinit_state(List, Exprn0, Exprn) },
- code_info__set_exprn_info(Exprn).
+%---------------------------------------------------------------------------%
-:- pred code_info__flatten_varlval_list(assoc_list(var, set(rval)),
- assoc_list(var, rval)).
-:- mode code_info__flatten_varlval_list(in, out) is det.
+code_info__effect_resume_point(ResumePoint, CodeModel, Code) -->
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(ResumePoints0, _ResumeKnown, CurfrMaxfr) },
+
+ { stack__top(ResumePoints0, OldResumePoint) ->
+ code_info__pick_first_resume_point(OldResumePoint, OldMap, _),
+ code_info__pick_first_resume_point(ResumePoint, NewMap, _),
+ map__keys(OldMap, OldKeys),
+ map__keys(NewMap, NewKeys),
+ set__list_to_set(OldKeys, OldKeySet),
+ set__list_to_set(NewKeys, NewKeySet),
+ require(set__subset(OldKeySet, NewKeySet),
+ "non-nested resume point variable sets")
+ ;
+ true
+ },
-code_info__flatten_varlval_list([], []).
-code_info__flatten_varlval_list([V - Rvals | Rest0], All) :-
- code_info__flatten_varlval_list(Rest0, Rest),
- set__to_sorted_list(Rvals, RvalList),
- code_info__flatten_varlval_list_2(RvalList, V, Rest1),
- list__append(Rest1, Rest, All).
+ { stack__push(ResumePoints0, ResumePoint, ResumePoints) },
+ { FailInfo = fail_info(ResumePoints, resume_point_known, CurfrMaxfr) },
+ code_info__set_fail_info(FailInfo),
+ ( { CodeModel = model_non } ->
+ { code_info__pick_stack_resume_point(ResumePoint,
+ _, StackLabel) },
+ { LabelConst = const(code_addr_const(StackLabel)) },
+ { Code = node([
+ assign(redoip(lval(maxfr)), LabelConst)
+ - "hijack redoip to effect resume point"
+ ]) }
+ ;
+ { Code = empty }
+ ).
-:- pred code_info__flatten_varlval_list_2(list(rval), var,
- assoc_list(var, rval)).
-:- mode code_info__flatten_varlval_list_2(in, in, out) is det.
+%---------------------------------------------------------------------------%
-code_info__flatten_varlval_list_2([], _V, []).
-code_info__flatten_varlval_list_2([R | Rs], V, [V - R | Rest]) :-
- code_info__flatten_varlval_list_2(Rs, V, Rest).
+code_info__top_resume_point(ResumePoint) -->
+ code_info__get_fail_info(FailInfo),
+ { FailInfo = fail_info(ResumePoints, _, _) },
+ { stack__top_det(ResumePoints, ResumePoint) }.
+
+code_info__set_resume_point_to_unknown -->
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(ResumePoints, _, CurfrMaxfr) },
+ { FailInfo = fail_info(ResumePoints, resume_point_unknown,
+ CurfrMaxfr) },
+ code_info__set_fail_info(FailInfo).
+
+code_info__set_resume_point_and_frame_to_unknown -->
+ code_info__get_fail_info(FailInfo0),
+ { FailInfo0 = fail_info(ResumePoints, _, _) },
+ { FailInfo = fail_info(ResumePoints, resume_point_unknown,
+ may_be_different) },
+ code_info__set_fail_info(FailInfo).
%---------------------------------------------------------------------------%
More information about the developers
mailing list