[m-dev.] for review: direct retry

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue Oct 10 17:03:23 AEDT 2000


For review by anyone.

The debugger's retry command at the moment works only from a final port for
the call to be retried, the reason being that the RTTI does not have the
information required to make sure that the state of the stacks is reset
correctly. If you invoke retry from a non-final port, the current
implementation skips forward to a final port and then does the retry;
this does not work if you get a core dump or a infinite loop during the forward
skip. This change adds the required info to the RTTI and thus enables
direct retries from the middle of calls.

The information added has two components. First, if a procedure that lives on
the nondet stack allocates any temporary nondet stack frames, then it must
record the old value of maxfr in a stack slot so that retry can restore it.
Second, if a procedure is tabled, then it must record the call table tip node
corresponding to the actual input arguments, so we can reset this node to
uninitialized (if we don't, then the retried call will find the active call
marker and report an infinite loop error).

The support for retries across minimal model calls is not finished yet.
Finding out what the right thing to do in such cases is a research project,
one that cannot even be started until minimal model tabling works reliably
in the *absence* of retries. However, such retries do grossly wrong things
at the moment; this change is a definite improvement. It attempts to perform
the retry from the fail port, since that is the only time when the minimal
model tabling data structures are quiescent. The "fail" command I added to
the debugger command set to let this be done is not complete yet and is
therefore undocumented; the problem is that a call to a model_non predicate
in a committed choice context will not get to the fail port. I added goal paths
to return layouts so that we will eventually be able to tell when execution
leaves a committed choice context surrounding an ancestor of a model_non
predicate call, but this functionality is not yet implemented.

compiler/stack_layout.m:
	Generate the three new fields.

compiler/continuation_info.m:
	Record the information about the new fields for later use by
	stack_layout.m.

	Add a new field to record the goal path of calls for their return
	layouts.

	Fix a screwed comment for the continuation_info data structure.

compiler/llds.m:
	Add a new field to call() instructions to hold the goal path of the
	call.

	Add a utility function for use by trace.m.

compiler/call_gen.m:
	Fill in this new field.

compiler/trace.m:
compiler/live_vars.m:
	Reserve the fixed stack slot for the saved maxfr if necessary,
	and if the call table tip node is needed, make sure that the variable
	holding its address is allocated a low-numbered stack slot (otherwise,
	its number may not fit into the MR_int_least8_t field in the
	proc_layout).

compiler/trace.m:
	If necessary, fill in the saved maxfr slot.

	If necessary, initialize the call table tip slot.

compiler/hlds_goal.m:
	Add a goal feature which marks its goal as defining the variable
	representing the call table tip node.

	Add a field to the goal path step representing quantification;
	the field says whether the quantification changes the determinism of
	the goal (i.e. whether it cuts away solutions).

compiler/hlds_pred.m:
compiler/hlds_out.m:
	Add two fields to proc_infos which (a) record which variable, if any,
	holds the call table tip node, and (b) record whether the procedure's
	layout structure needs to reserve a slot for the saved value of maxfr.

compiler/table_gen.m:
	Put this feature on the appropriate goal.

	Also, rename a predicate to make it reflect its purpose better.

compiler/code_gen.m:
	Generate code to put the call table tip variable in its stack slot
	immediately after it has been generated.

	Add a sanity check to ensure that if a procedure that lives on the det
	stack can create a temporary nondet frame, and debugging is enabled,
	then it did have a stack slot reserved for the saved maxfr.

compiler/code_util.m:
	Add a predicate to make a conservative prediction of whether a
	procedure may allocate a temporary nondet stack frame. We cannot
	just generate the code and see, because the code generator needs to
	know which variables live in which stack slots, and we cannot decide
	that until we know whether we need a stack slot for the saved value of
	maxfr.

	Make an unrelated predicate semidet procedure use a det helper, in
	order to make it more robust in the face of changes to the HLDS
	(e.g. it was missing code for handling bi_implications).

compiler/code_info.m:
	Record whether a procedure has in fact created a temporary nondet stack
	frame.

compiler/handle_options.m:
	Disable hijacks if debugging is enabled. This is required for the
	correctness of the code we use to restore the stacks for direct
	retries.

compiler/*.m:
	Trivial changes to conform to changes in data structures.

runtime/mercury_stack_layout.h:
	Add three new fields to proc layouts: the numbers of the stack slots
	(if any) storing the saved maxfr and the call table tip, and a
	representation of the procedure's evaluation method.

runtime/mercury_stack_trace.[ch]:
	Now that return layouts contain goal paths, print them in stack dumps
	only if the include_trace_data flag is set (in mdb, this requires the
	-d flag of the "stack" command).

	Pass this flag around directly, instead of encoding its value in
	the NULL vs non-NULL values of sp and curfr.

runtime/mercury_regorder.h:
	Provide a mechanism to access the values of the first few rN registers
	from a save area, for use in debugging low-level C code in the runtime
	and the trace directories.

trace/mercury_trace.[ch]:
	Reimplement MR_trace_retry to allow retries from the middle.
	If the stack segment being retried over contains minimal model
	procedures, we must still arrange to skip to the end of the retried
	call. If this call is a minimal model generator, skipping to just any
	final port is not sufficient to guarantee correctness on retry; to
	ensure that subgoal is complete, we must skip to a fail port.

trace/mercury_trace.[ch]:
trace/mercury_trace_internal.c:
	Implement a debugger command, "fail", which skips to the fail port or
	the exception port of the specified ancestor. Since procedures that are
	not model_non are not guaranteed to get to such a port, this
	command reports an error if the specified call is not model_non.
	Actually, even calls to model_non procedures may not get to the fail
	port, as explained above; this is why the command is not yet
	documented.

trace/mercury_trace.c:
trace/mercury_trace_util.[ch]:
	Move some functions to print parts of the Mercury abstract machine
	state from mercury_trace to mercury_trace_util, so that they are
	available for use in debugging e.g. mercury_trace_declarative.

trace/mercury_trace_internal.c:
trace/mercury_trace_external.c:
trace/mercury_trace_declarative.c:
	Use the new implementation of retries. At the moment, only the
	internal debugger implements the full functionality. The declarative
	debugger issues retry commands only from situations where the missing
	functionality is not (yet) needed. The external debugger should
	continue to work correctly, but Erwan may wish to update it to
	exploit the availability of the fail command.

trace/mercury_trace*.[ch]:
	Fix MR_prefixes, and a signed/unsigned mismatch.

doc/user_guide.texi:
	Document the new "fail" command, but comment it out for now.

tests/debugger/retry.{m,inp,exp,exp2}:
	A new test case for exercising retry.

tests/debugger/Mmakefile:
	Enable the new test case.

tests/debugger/*.exp:
	Update the expected output, given the extra info now output e.g. for
	exception events and detailed stack traces.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.144
diff -u -r1.144 call_gen.m
--- compiler/call_gen.m	2000/09/20 00:21:36	1.144
+++ compiler/call_gen.m	2000/10/01 07:18:29
@@ -80,11 +80,12 @@
 	code_info__get_next_label(ReturnLabel),
 	{ call_gen__call_comment(CodeModel, CallComment) },
 	{ goal_info_get_context(GoalInfo, Context) },
+	{ goal_info_get_goal_path(GoalInfo, GoalPath) },
 	{ CallCode = node([
 		livevals(LiveVals)
 			- "",
 		call(Address, label(ReturnLabel), ReturnLiveLvalues, Context,
-			CallModel)
+			GoalPath, CallModel)
 			- CallComment,
 		label(ReturnLabel)
 			- "continuation label"
@@ -167,11 +168,12 @@
 		% Make the call.
 	code_info__get_next_label(ReturnLabel),
 	{ goal_info_get_context(GoalInfo, Context) },
+	{ goal_info_get_goal_path(GoalInfo, GoalPath) },
 	{ CallCode = node([
 		livevals(LiveVals)
 			- "",
 		call(CodeAddr, label(ReturnLabel), ReturnLiveLvalues,
-			Context, CallModel)
+			Context, GoalPath, CallModel)
 			- "Setup and call",
 		label(ReturnLabel)
 			- "Continuation label"
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.85
diff -u -r1.85 code_gen.m
--- compiler/code_gen.m	2000/10/03 00:33:58	1.85
+++ compiler/code_gen.m	2000/10/10 03:02:09
@@ -61,7 +61,7 @@
 
 :- import_module call_gen, unify_gen, ite_gen, switch_gen, disj_gen.
 :- import_module par_conj_gen, pragma_c_gen, commit_gen.
-:- import_module continuation_info, trace, options, hlds_out.
+:- import_module continuation_info, trace, trace_params, options, hlds_out.
 :- import_module code_aux, middle_rec, passes_aux, llds_out.
 :- import_module code_util, type_util, mode_util, goal_util.
 :- import_module prog_data, prog_out, prog_util, instmap, globals.
@@ -258,6 +258,28 @@
 	code_info__get_max_reg_in_use_at_trace(MaxTraceReg, CodeInfo, _),
 	code_info__get_cell_counter(CellCounter, CodeInfo, _),
 
+	globals__get_trace_level(Globals, TraceLevel),
+	code_info__get_created_temp_frame(CreatedTempFrame, CodeInfo, _),
+
+	(
+		trace_level_is_none(TraceLevel) = no,
+		CreatedTempFrame = yes,
+		CodeModel \= model_non
+	->
+			% If tracing is enabled, the procedure lives on
+			% the det stack and the code created any temporary
+			% nondet stack frames, then we must have reserved a
+			% stack slot for storing the value of maxfr; if we
+			% didn't, a retry command in the debugger from a point
+			% in the middle of this procedure will do the wrong
+			% thing.
+		proc_info_get_need_maxfr_slot(ProcInfo, HaveMaxfrSlot),
+		require(unify(HaveMaxfrSlot, yes),
+			"should have reserved a slot for maxfr, but didn't")
+	;
+		true
+	),
+
 		% Turn the code tree into a list.
 	tree__flatten(CodeTree, FragmentList),
 		% Now the code is a list of code fragments (== list(instr)),
@@ -282,12 +304,13 @@
 		code_info__get_layout_info(InternalMap, CodeInfo, _),
 		code_util__make_local_entry_label(ModuleInfo, PredId, ProcId,
 			no, EntryLabel),
+		proc_info_eval_method(ProcInfo, EvalMethod),
 		proc_info_get_initial_instmap(ProcInfo, ModuleInfo, InstMap0),
 		proc_info_varset(ProcInfo, VarSet),
 		ProcLayout = proc_layout_info(EntryLabel, Detism, TotalSlots,
-			MaybeSuccipSlot, MaybeTraceCallLabel, MaxTraceReg,
-			Goal, InstMap0, TraceSlotInfo, ForceProcId,
-			VarSet, InternalMap),
+			MaybeSuccipSlot, EvalMethod, MaybeTraceCallLabel,
+			MaxTraceReg, Goal, InstMap0, TraceSlotInfo,
+			ForceProcId, VarSet, InternalMap),
 		global_data_add_new_proc_layout(GlobalData0,
 			proc(PredId, ProcId), ProcLayout, GlobalData1)
 	;
@@ -315,9 +338,9 @@
 	Proc = c_procedure(Name, Arity, proc(PredId, ProcId), Instructions,
 		ProcLabel, LabelCounter, ContainsReconstruction).
 
-:- pred maybe_add_tabling_pointer_var(module_info, pred_id, proc_id, proc_info,
-	proc_label, global_data, global_data).
-:- mode maybe_add_tabling_pointer_var(in, in, in, in, in, in, out) is det.
+:- pred maybe_add_tabling_pointer_var(module_info::in,
+	pred_id::in, proc_id::in, proc_info::in, proc_label::in,
+	global_data::in, global_data::out) is det.
 
 maybe_add_tabling_pointer_var(ModuleInfo, PredId, ProcId, ProcInfo, ProcLabel,
 		GlobalData0, GlobalData) :-
@@ -538,7 +561,7 @@
 			MaybeFailExternalInfo = no,
 			TraceFailCode = empty
 		},
-		{ TraceSlotInfo = trace_slot_info(_, _, yes(_)) ->
+		{ TraceSlotInfo ^ slot_trail = yes(_) ->
 			DiscardTraceTicketCode = node([
 				discard_ticket - "discard retry ticket"
 			])
@@ -802,7 +825,7 @@
 			])
 		},
 		{
-			TraceSlotInfo = trace_slot_info(_, _, yes(_)),
+			TraceSlotInfo ^ slot_trail = yes(_),
 			CodeModel \= model_non
 		->
 			PruneTraceTicketCode = node([
@@ -943,7 +966,32 @@
 			)
 		},
 
-		code_gen__generate_goal_2(Goal, GoalInfo, CodeModel, Code),
+		code_gen__generate_goal_2(Goal, GoalInfo, CodeModel, GoalCode),
+
+			% If the predicate's evaluation method is memo,
+			% loopcheck or minimal model, the goal generated
+			% the variable that represents the call table tip,
+			% *and* tracing is enabled, then we save this variable
+			% to its stack slot. This is necessary to enable
+			% retries across this procedure to reset the call table
+			% entry to uninitialized, effectively removing the
+			% call table entry.
+		(
+			{ goal_info_get_features(GoalInfo, Features) },
+			{ set__member(call_table_gen, Features) },
+			code_info__get_proc_info(ProcInfo),
+			{ proc_info_get_call_table_tip(ProcInfo,
+				MaybeCallTableVar) },
+				% MaybeCallTableVar will be `no' unless
+				% tracing is enabled.
+			{ MaybeCallTableVar = yes(CallTableVar) }
+		->
+			code_info__save_variables_on_stack([CallTableVar],
+				SaveCode),
+			{ Code = tree(GoalCode, SaveCode) }
+		;
+			{ Code = GoalCode }
+		),
 
 			% Make live any variables which subsequent goals
 			% will expect to be live, but were not generated
@@ -1066,12 +1114,12 @@
 		set__insert(LiveVals0, stackvar(StackLoc), LiveVals1),
 		Instrn = livevals(LiveVals1)
         ;
-		Instrn0 = call(Target, ReturnLabel, LiveVals0, Context, CM)
+		Instrn0 = call(Target, ReturnLabel, LiveVals0, Context, GP, CM)
 	->
 		map__init(Empty),
 		LiveVals  = [live_lvalue(direct(stackvar(StackLoc)),
 				succip, Empty) | LiveVals0],
-		Instrn = call(Target, ReturnLabel, LiveVals, Context, CM)
+		Instrn = call(Target, ReturnLabel, LiveVals, Context, GP, CM)
 	;
 		Instrn = Instrn0
 	),
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.256
diff -u -r1.256 code_info.m
--- compiler/code_info.m	2000/10/03 00:34:01	1.256
+++ compiler/code_info.m	2000/10/04 06:46:07
@@ -150,6 +150,11 @@
 :- pred code_info__set_max_reg_in_use_at_trace(int::in,
 	code_info::in, code_info::out) is det.
 
+		% Get the flag which is true iff the procedure has so far
+		% emitted code that creates a temporary nondet stack frame.
+:- pred code_info__get_created_temp_frame(bool::out,
+	code_info::in, code_info::out) is det.
+
 %---------------------------------------------------------------------------%
 
 :- implementation.
@@ -208,6 +213,9 @@
 :- pred code_info__set_non_common_static_data(list(comp_gen_c_data)::in,
 	code_info::in, code_info::out) is det.
 
+:- pred code_info__set_created_temp_frame(bool::in,
+	code_info::in, code_info::out) is det.
+
 %---------------------------------------------------------------------------%
 
 	% The code_info structure has three groups of fields.
@@ -307,7 +315,7 @@
 				% Static data structures created for this
 				% procedure which do not need to be scanned
 				% by llds_common.
-		max_reg_used :: int
+		max_reg_used :: int,
 				% At each call to MR_trace, we compute the
 				% highest rN register number that contains
 				% a useful value. This slot contains the
@@ -317,6 +325,9 @@
 				% are equal to or smaller than this field.
 				% This slot contains -1 if tracing is not
 				% enabled.
+		created_temp_frame:: bool
+				% True iff the procedure has created one or
+				% more temporary nondet frames.
 	).
 
 :- type var_locns_info
@@ -377,7 +388,7 @@
 	set__init(Zombies),
 	map__init(LayoutMap),
 	code_info__max_var_slot(StackSlots, VarSlotMax),
-	trace__reserved_slots(ProcInfo, Globals, FixedSlots),
+	trace__reserved_slots(ProcInfo, Globals, FixedSlots, _),
 	int__max(VarSlotMax, FixedSlots, SlotMax),
 	CodeInfo0 = code_info(
 		Globals,
@@ -403,22 +414,25 @@
 		0,
 		TempContentMap,
 		[],
-		-1
+		-1,
+		no
 	),
-	code_info__init_maybe_trace_info(TraceLevel, Globals, TraceSlotInfo,
-		CodeInfo0, CodeInfo1),
+	code_info__init_maybe_trace_info(TraceLevel, Globals, ProcInfo,
+		TraceSlotInfo, CodeInfo0, CodeInfo1),
 	code_info__init_fail_info(CodeModel, MaybeFailVars, ResumePoint,
 		CodeInfo1, CodeInfo).
 
 :- pred code_info__init_maybe_trace_info(trace_level::in, globals::in,
-	trace_slot_info::out, code_info::in, code_info::out) is det.
+	proc_info::in, trace_slot_info::out,
+	code_info::in, code_info::out) is det.
 
-code_info__init_maybe_trace_info(TraceLevel, Globals, TraceSlotInfo) -->
+code_info__init_maybe_trace_info(TraceLevel, Globals, ProcInfo, TraceSlotInfo)
+		-->
 	( { trace_level_is_none(TraceLevel) = no } ->
-		trace__setup(Globals, TraceSlotInfo, TraceInfo),
+		trace__setup(ProcInfo, Globals, TraceSlotInfo, TraceInfo),
 		code_info__set_maybe_trace_info(yes(TraceInfo))
 	;
-		{ TraceSlotInfo = trace_slot_info(no, no, no) }
+		{ TraceSlotInfo = trace_slot_info(no, no, no, no, no) }
 	).
 
 %---------------------------------------------------------------------------%
@@ -445,6 +459,7 @@
 code_info__get_temp_content_map(CI^temp_contents, CI, CI).
 code_info__get_non_common_static_data(CI^comp_gen_c_data, CI, CI).
 code_info__get_max_reg_in_use_at_trace(CI^max_reg_used, CI, CI).
+code_info__get_created_temp_frame(CI^created_temp_frame, CI, CI).
 
 %---------------------------------------------------------------------------%
 
@@ -463,6 +478,7 @@
 code_info__set_temp_content_map(CM, CI, CI^temp_contents := CM).
 code_info__set_non_common_static_data(CG, CI, CI^comp_gen_c_data := CG).
 code_info__set_max_reg_in_use_at_trace(MR, CI, CI^max_reg_used := MR).
+code_info__set_created_temp_frame(MR, CI, CI^created_temp_frame := MR).
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
@@ -894,12 +910,12 @@
 
 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, _,  _,  _,  _,  _,  _,  _,  _ ),
+	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, PG, PH),
+		_,  _,  _,  _,  _,  _,  PA, PB, PC, PD, PE, PF, PG, PH, PI),
 	NextCI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
-		LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG, PH).
+		LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG, PH, PI).
 
 code_info__reset_resume_known(BranchStart) -->
 	{ BranchStart = position_info(BranchStartCI) },
@@ -1944,6 +1960,7 @@
 		mkframe(temp_frame(Kind), Redoip)
 			- Comment
 	]) },
+	code_info__set_created_temp_frame(yes),
 	code_info__get_fail_info(FailInfo0),
 	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, _, CondEnv, Allow) },
 	{ FailInfo = fail_info(ResumePoints, ResumeKnown, may_be_different,
Index: compiler/code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_util.m,v
retrieving revision 1.125
diff -u -r1.125 code_util.m
--- compiler/code_util.m	2000/09/20 00:21:45	1.125
+++ compiler/code_util.m	2000/10/01 07:18:29
@@ -103,6 +103,9 @@
 :- pred code_util__goal_list_may_allocate_heap(list(hlds_goal)).
 :- mode code_util__goal_list_may_allocate_heap(in) is semidet.
 
+:- pred code_util__goal_may_alloc_temp_frame(hlds_goal).
+:- mode code_util__goal_may_alloc_temp_frame(in) is semidet.
+
 	% Negate a condition.
 	% This is used mostly just to make the generated code more readable.
 
@@ -445,52 +448,160 @@
 
 %-----------------------------------------------------------------------------%
 
-	% This code may _look_ nondeterministic, but it's really semidet,
-	% and Mercury is smart enough to know this.
+code_util__goal_may_allocate_heap(Goal) :-
+	code_util__goal_may_allocate_heap(Goal, yes).
 
-code_util__goal_may_allocate_heap(Goal - _GoalInfo) :-
-	code_util__goal_may_allocate_heap_2(Goal).
+code_util__goal_list_may_allocate_heap(Goals) :-
+	code_util__goal_list_may_allocate_heap(Goals, yes).
 
-:- pred code_util__goal_may_allocate_heap_2(hlds_goal_expr).
-:- mode code_util__goal_may_allocate_heap_2(in) is semidet.
+:- pred code_util__goal_may_allocate_heap(hlds_goal::in, bool::out) is det.
 
-code_util__goal_may_allocate_heap_2(generic_call(_, _, _, _)).
-code_util__goal_may_allocate_heap_2(call(_, _, _, Builtin, _, _)) :-
-	Builtin \= inline_builtin.
-code_util__goal_may_allocate_heap_2(
-		unify(_, _, _, construct(_,_,Args,_,_,_,_), _)) :-
-	Args = [_|_].
-code_util__goal_may_allocate_heap_2(some(_Vars, _, Goal)) :-
-	code_util__goal_may_allocate_heap(Goal).
-code_util__goal_may_allocate_heap_2(not(Goal)) :-
-	code_util__goal_may_allocate_heap(Goal).
-code_util__goal_may_allocate_heap_2(conj(Goals)) :-
-	code_util__goal_list_may_allocate_heap(Goals).
-code_util__goal_may_allocate_heap_2(disj(Goals, _)) :-
-	code_util__goal_list_may_allocate_heap(Goals).
-code_util__goal_may_allocate_heap_2(switch(_Var, _Det, Cases, _)) :-
-	code_util__cases_may_allocate_heap(Cases).
-code_util__goal_may_allocate_heap_2(if_then_else(_Vars, A, B, C, _)) :-
-	(
-		code_util__goal_may_allocate_heap(A)
-	;	
-		code_util__goal_may_allocate_heap(B)
+code_util__goal_may_allocate_heap(Goal - _GoalInfo, May) :-
+	code_util__goal_may_allocate_heap_2(Goal, May).
+
+:- pred code_util__goal_may_allocate_heap_2(hlds_goal_expr::in, bool::out)
+	is det.
+
+code_util__goal_may_allocate_heap_2(generic_call(_, _, _, _), yes).
+code_util__goal_may_allocate_heap_2(call(_, _, _, Builtin, _, _), May) :-
+	( Builtin = inline_builtin ->
+		May = no
 	;
-		code_util__goal_may_allocate_heap(C)
+		May = yes
 	).
+code_util__goal_may_allocate_heap_2(unify(_, _, _, Unification, _), May) :-
+	( Unification = construct(_,_,Args,_,_,_,_), Args = [_|_] ->
+		May = yes
+	;
+		May = no
+	).
+	% We cannot safely say that a C code fragment does not allocate memory
+	% without knowing all the #defined macros that expand to incr_hp and
+	% variants thereof.
+code_util__goal_may_allocate_heap_2(pragma_foreign_code(_,_,_,_,_,_,_,_), yes).
+code_util__goal_may_allocate_heap_2(some(_Vars, _, Goal), May) :-
+	code_util__goal_may_allocate_heap(Goal, May).
+code_util__goal_may_allocate_heap_2(not(Goal), May) :-
+	code_util__goal_may_allocate_heap(Goal, May).
+code_util__goal_may_allocate_heap_2(conj(Goals), May) :-
+	code_util__goal_list_may_allocate_heap(Goals, May).
+code_util__goal_may_allocate_heap_2(par_conj(_, _), yes).
+code_util__goal_may_allocate_heap_2(disj(Goals, _), May) :-
+	code_util__goal_list_may_allocate_heap(Goals, May).
+code_util__goal_may_allocate_heap_2(switch(_Var, _Det, Cases, _), May) :-
+	code_util__cases_may_allocate_heap(Cases, May).
+code_util__goal_may_allocate_heap_2(if_then_else(_Vars, C, T, E, _), May) :-
+	( code_util__goal_may_allocate_heap(C, yes) ->
+		May = yes
+	; code_util__goal_may_allocate_heap(T, yes) ->
+		May = yes
+	;
+		code_util__goal_may_allocate_heap(E, May)
+	).
+code_util__goal_may_allocate_heap_2(bi_implication(G1, G2), May) :-
+	( code_util__goal_may_allocate_heap(G1, yes) ->
+		May = yes
+	;
+		code_util__goal_may_allocate_heap(G2, May)
+	).
+
+:- pred code_util__goal_list_may_allocate_heap(list(hlds_goal)::in, bool::out)
+	is det.
+
+code_util__goal_list_may_allocate_heap([], no).
+code_util__goal_list_may_allocate_heap([Goal | Goals], May) :-
+	( code_util__goal_may_allocate_heap(Goal, yes) ->
+		May = yes
+	;
+		code_util__goal_list_may_allocate_heap(Goals, May)
+	).
 
-:- pred code_util__cases_may_allocate_heap(list(case)).
-:- mode code_util__cases_may_allocate_heap(in) is semidet.
+:- pred code_util__cases_may_allocate_heap(list(case)::in, bool::out) is det.
 
-code_util__cases_may_allocate_heap([case(_, Goal) | _]) :-
-	code_util__goal_may_allocate_heap(Goal).
-code_util__cases_may_allocate_heap([_ | Cases]) :-
-	code_util__cases_may_allocate_heap(Cases).
+code_util__cases_may_allocate_heap([], no).
+code_util__cases_may_allocate_heap([case(_, Goal) | Cases], May) :-
+	( code_util__goal_may_allocate_heap(Goal, yes) ->
+		May = yes
+	;
+		code_util__cases_may_allocate_heap(Cases, May)
+	).
+
+%-----------------------------------------------------------------------------%
 
-code_util__goal_list_may_allocate_heap([Goal | _]) :-
-	code_util__goal_may_allocate_heap(Goal).
-code_util__goal_list_may_allocate_heap([_ | Goals]) :-
-	code_util__goal_list_may_allocate_heap(Goals).
+code_util__goal_may_alloc_temp_frame(Goal) :-
+	code_util__goal_may_alloc_temp_frame(Goal, yes).
+
+:- pred code_util__goal_may_alloc_temp_frame(hlds_goal::in, bool::out) is det.
+
+code_util__goal_may_alloc_temp_frame(Goal - _GoalInfo, May) :-
+	code_util__goal_may_alloc_temp_frame_2(Goal, May).
+
+:- pred code_util__goal_may_alloc_temp_frame_2(hlds_goal_expr::in, bool::out)
+	is det.
+
+code_util__goal_may_alloc_temp_frame_2(generic_call(_, _, _, _), no).
+code_util__goal_may_alloc_temp_frame_2(call(_, _, _, _, _, _), no).
+code_util__goal_may_alloc_temp_frame_2(unify(_, _, _, _, _), no).
+	% We cannot safely say that a C code fragment does not allocate
+	% temporary nondet frames without knowing all the #defined macros
+	% that expand to mktempframe and variants thereof. The performance
+	% impact of being too conservative is probably not too bad.
+code_util__goal_may_alloc_temp_frame_2(pragma_foreign_code(_,_,_,_,_,_,_,_),
+		yes).
+code_util__goal_may_alloc_temp_frame_2(some(_Vars, _, Goal), May) :-
+	Goal = _ - GoalInfo,
+	goal_info_get_code_model(GoalInfo, CodeModel),
+	( CodeModel = model_non ->
+		May = yes
+	;
+		code_util__goal_may_alloc_temp_frame(Goal, May)
+	).
+code_util__goal_may_alloc_temp_frame_2(not(Goal), May) :-
+	code_util__goal_may_alloc_temp_frame(Goal, May).
+code_util__goal_may_alloc_temp_frame_2(conj(Goals), May) :-
+	code_util__goal_list_may_alloc_temp_frame(Goals, May).
+code_util__goal_may_alloc_temp_frame_2(par_conj(Goals, _), May) :-
+	code_util__goal_list_may_alloc_temp_frame(Goals, May).
+code_util__goal_may_alloc_temp_frame_2(disj(Goals, _), May) :-
+	code_util__goal_list_may_alloc_temp_frame(Goals, May).
+code_util__goal_may_alloc_temp_frame_2(switch(_Var, _Det, Cases, _), May) :-
+	code_util__cases_may_alloc_temp_frame(Cases, May).
+code_util__goal_may_alloc_temp_frame_2(if_then_else(_Vars, C, T, E, _), May) :-
+	( code_util__goal_may_alloc_temp_frame(C, yes) ->
+		May = yes
+	; code_util__goal_may_alloc_temp_frame(T, yes) ->
+		May = yes
+	;
+		code_util__goal_may_alloc_temp_frame(E, May)
+	).
+code_util__goal_may_alloc_temp_frame_2(bi_implication(G1, G2), May) :-
+	( code_util__goal_may_alloc_temp_frame(G1, yes) ->
+		May = yes
+	;
+		code_util__goal_may_alloc_temp_frame(G2, May)
+	).
+
+:- pred code_util__goal_list_may_alloc_temp_frame(list(hlds_goal)::in,
+	bool::out) is det.
+
+code_util__goal_list_may_alloc_temp_frame([], no).
+code_util__goal_list_may_alloc_temp_frame([Goal | Goals], May) :-
+	( code_util__goal_may_alloc_temp_frame(Goal, yes) ->
+		May = yes
+	;
+		code_util__goal_list_may_alloc_temp_frame(Goals, May)
+	).
+
+:- pred code_util__cases_may_alloc_temp_frame(list(case)::in, bool::out)
+	is det.
+
+code_util__cases_may_alloc_temp_frame([], no).
+code_util__cases_may_alloc_temp_frame([case(_, Goal) | Cases], May) :-
+	( code_util__goal_may_alloc_temp_frame(Goal, yes) ->
+		May = yes
+	;
+		code_util__cases_may_alloc_temp_frame(Cases, May)
+	).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.36
diff -u -r1.36 continuation_info.m
--- compiler/continuation_info.m	2000/09/25 04:37:08	1.36
+++ compiler/continuation_info.m	2000/10/04 05:16:40
@@ -75,29 +75,37 @@
 					% arguments on procedure entry, for
 					% use in implementing retry in the
 					% debugger.
+			eval_method	:: eval_method,
+					% Of the procedure.
 			call_label	:: maybe(label),
+					% If the trace level is not none,
+					% this contains the label associated
+					% with the call event, whose stack
+					% layout says which variables were
+					% live and where on entry.
+			max_trace_reg	:: int,
 					% The number of the highest numbered
 					% rN register that can contain useful
 					% information during a call to MR_trace
 					% from within this procedure.
-			max_trace_reg	:: int,
-					% Info about the stack slots used
-					% for tracing.
 			proc_body	:: hlds_goal,
+					% The body of the procedure.
 			initial_instmap	:: instmap,
 					% The instmap at the start of the
 					% procedure body.
 			trace_slot_info	:: trace_slot_info,
+					% Info about the stack slots used
+					% for tracing.
+			need_proc_id	:: bool,
 					% Do we require the procedure id
 					% section of the procedure layout
 					% to be present, even if the option
 					% procid_stack_layout is not set?
-			need_proc_id	:: bool,
-					% The names of all the variables.
 			varset		:: prog_varset,
+					% The names of all the variables.
+			internal_map	:: proc_label_layout_info
 					% Info for each internal label,
 					% needed for basic_stack_layouts.
-			internal_map	:: proc_label_layout_info
 		).
 
 	%
@@ -198,7 +206,7 @@
 
 :- type return_layout_info
 	--->	return_layout_info(
-			list(pair(code_addr, prog_context)),
+			assoc_list(code_addr, pair(prog_context, goal_path)),
 			layout_label_info
 		).
 
@@ -337,7 +345,9 @@
 			label,		% the return label
 			code_addr,	% the target of the call
 			list(liveinfo),	% what is live on return
-			term__context	% the position of the call in source
+			term__context,	% the position of the call in source
+			goal_path	% the position of the call in the body;
+					% meaningful only if tracing is enabled
 		).
 
 	%
@@ -355,9 +365,10 @@
 	global_data_get_proc_layout(GlobalData0, PredProcId, ProcLayoutInfo0),
 	Internals0 = ProcLayoutInfo0^internal_map,
 	GetCallInfo = lambda([Instr::in, Call::out] is semidet, (
-		Instr = call(Target, label(ReturnLabel), LiveInfo, Context, _)
-			- _Comment,
-		Call = call_info(ReturnLabel, Target, LiveInfo, Context)
+		Instr = call(Target, label(ReturnLabel), LiveInfo, Context,
+			GoalPath, _) - _Comment,
+		Call = call_info(ReturnLabel, Target, LiveInfo, Context,
+			GoalPath)
 	)),
 	list__filter_map(GetCallInfo, Instructions, Calls),
 
@@ -380,7 +391,8 @@
 
 continuation_info__process_continuation(WantReturnInfo, CallInfo,
 		Internals0, Internals) :-
-	CallInfo = call_info(ReturnLabel, Target, LiveInfoList, Context),
+	CallInfo = call_info(ReturnLabel, Target, LiveInfoList,
+		Context, MaybeGoalPath),
 	( map__search(Internals0, ReturnLabel, Internal0) ->
 		Internal0 = internal_layout_info(Port0, Resume0, Return0)
 	;
@@ -394,7 +406,8 @@
 		(
 			Return0 = no,
 			Layout = layout_label_info(VarInfoSet, TypeInfoMap),
-			ReturnInfo = return_layout_info([Target - Context],
+			ReturnInfo = return_layout_info(
+				[Target - (Context - MaybeGoalPath)],
 				Layout),
 			Return = yes(ReturnInfo)
 		;
@@ -410,7 +423,8 @@
 			set__intersect(LV0, VarInfoSet, LV),
 			map__intersect(set__intersect, TV0, TypeInfoMap, TV),
 			Layout = layout_label_info(LV, TV),
-			TargetContexts = [Target - Context | TargetsContexts0],
+			TargetContexts = [Target - (Context - MaybeGoalPath)
+				| TargetsContexts0],
 			ReturnInfo = return_layout_info(TargetContexts,
 				Layout),
 			Return = yes(ReturnInfo)
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.48
diff -u -r1.48 dupelim.m
--- compiler/dupelim.m	2000/08/11 08:19:02	1.48
+++ compiler/dupelim.m	2000/10/01 07:18:31
@@ -306,7 +306,7 @@
 		standardize_rval(Rval1, Rval),
 		Instr = assign(Lval, Rval)
 	;
-		Instr1 = call(_, _, _, _, _),
+		Instr1 = call(_, _, _, _, _, _),
 		Instr = Instr1
 	;
 		Instr1 = mkframe(_, _),
@@ -580,7 +580,7 @@
 		most_specific_rval(Rval1, Rval2, Rval),
 		Instr = assign(Lval, Rval)
 	;
-		Instr1 = call(_, _, _, _, _),
+		Instr1 = call(_, _, _, _, _, _),
 		Instr2 = Instr1,
 		Instr = Instr1
 	;
Index: compiler/frameopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/frameopt.m,v
retrieving revision 1.76
diff -u -r1.76 frameopt.m
--- compiler/frameopt.m	2000/08/11 08:19:03	1.76
+++ compiler/frameopt.m	2000/10/01 07:18:31
@@ -534,7 +534,7 @@
 			list__member(Instr, Instrs),
 			Instr = Uinstr - _,
 			(
-				Uinstr = call(_, _, _, _, _)
+				Uinstr = call(_, _, _, _, _, _)
 			;
 				Uinstr = mkframe(_, _)
 			;
@@ -667,7 +667,7 @@
 		list__member(Instr, Instrs),
 		Instr = Uinstr - _,
 		(
-			Uinstr = call(_, _, _, _, _)
+			Uinstr = call(_, _, _, _, _, _)
 		;
 			% Only may_call_mercury pragma_c's can clobber succip.
 			Uinstr = pragma_c(_, _, may_call_mercury, _, _, _, _)
Index: compiler/goal_path.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/goal_path.m,v
retrieving revision 1.9
diff -u -r1.9 goal_path.m
--- compiler/goal_path.m	2000/08/09 07:46:31	1.9
+++ compiler/goal_path.m	2000/10/05 12:08:09
@@ -42,18 +42,19 @@
 
 fill_goal_slots(Expr0 - Info0, Path0, SlotInfo, Expr - Info) :-
 	goal_info_set_goal_path(Info0, Path0, Info),
-	fill_expr_slots(Expr0, Path0, SlotInfo, Expr).
+	fill_expr_slots(Expr0, Info, Path0, SlotInfo, Expr).
 
-:- pred fill_expr_slots(hlds_goal_expr::in, goal_path::in, slot_info::in,
-	hlds_goal_expr::out) is det.
+:- pred fill_expr_slots(hlds_goal_expr::in, hlds_goal_info::in, goal_path::in,
+	slot_info::in, hlds_goal_expr::out) is det.
 
-fill_expr_slots(conj(Goals0), Path0, SlotInfo, conj(Goals)) :-
+fill_expr_slots(conj(Goals0), _, Path0, SlotInfo, conj(Goals)) :-
 	fill_conj_slots(Goals0, Path0, 0, SlotInfo, Goals).
-fill_expr_slots(par_conj(Goals0, SM), Path0, SlotInfo, par_conj(Goals, SM)) :-
+fill_expr_slots(par_conj(Goals0, SM), _, Path0, SlotInfo,
+		par_conj(Goals, SM)) :-
 	fill_conj_slots(Goals0, Path0, 0, SlotInfo, Goals).
-fill_expr_slots(disj(Goals0, B), Path0, SlotInfo, disj(Goals, B)) :-
+fill_expr_slots(disj(Goals0, B), _, Path0, SlotInfo, disj(Goals, B)) :-
 	fill_disj_slots(Goals0, Path0, 0, SlotInfo, Goals).
-fill_expr_slots(switch(Var, B, Cases0, D), Path0, SlotInfo,
+fill_expr_slots(switch(Var, B, Cases0, D), _, Path0, SlotInfo,
 		switch(Var, B, Cases, D)) :-
 	SlotInfo = slot_info(VarTypes, ModuleInfo),
 	map__lookup(VarTypes, Var, Type),
@@ -66,21 +67,30 @@
 		NumCases = -1
 	),
 	fill_switch_slots(Cases0, Path0, 0, NumCases, SlotInfo, Cases).
-fill_expr_slots(not(Goal0), Path0, SlotInfo, not(Goal)) :-
+fill_expr_slots(not(Goal0), _, Path0, SlotInfo, not(Goal)) :-
 	fill_goal_slots(Goal0, [neg | Path0], SlotInfo, Goal).
-fill_expr_slots(some(A, B, Goal0), Path0, SlotInfo, some(A, B, Goal)) :-
-	fill_goal_slots(Goal0, [exist | Path0], SlotInfo, Goal).
-fill_expr_slots(if_then_else(A, Cond0, Then0, Else0, E), Path0, SlotInfo,
+fill_expr_slots(some(A, B, Goal0), OuterInfo, Path0, SlotInfo,
+		some(A, B, Goal)) :-
+	Goal0 = _ - InnerInfo,
+	goal_info_get_code_model(OuterInfo, OuterModel),
+	goal_info_get_code_model(InnerInfo, InnerModel),
+	( InnerModel = OuterModel ->
+		MaybeCut = no_cut
+	;
+		MaybeCut = cut
+	),
+	fill_goal_slots(Goal0, [exist(MaybeCut) | Path0], SlotInfo, Goal).
+fill_expr_slots(if_then_else(A, Cond0, Then0, Else0, E), _, Path0, SlotInfo,
 		if_then_else(A, Cond, Then, Else, E)) :-
 	fill_goal_slots(Cond0, [ite_cond | Path0], SlotInfo, Cond),
 	fill_goal_slots(Then0, [ite_then | Path0], SlotInfo, Then),
 	fill_goal_slots(Else0, [ite_else | Path0], SlotInfo, Else).
-fill_expr_slots(call(A,B,C,D,E,F), _Path0, _Slot, call(A,B,C,D,E,F)).
-fill_expr_slots(generic_call(A,B,C,D), _Path0, _Slot, generic_call(A,B,C,D)).
-fill_expr_slots(unify(A,B,C,D,E), _Path0, _Slot, unify(A,B,C,D,E)).
-fill_expr_slots(pragma_foreign_code(A,B,C,D,E,F,G,H), _Path0, _Slot,
+fill_expr_slots(call(A,B,C,D,E,F), _, _, _, call(A,B,C,D,E,F)).
+fill_expr_slots(generic_call(A,B,C,D), _, _, _, generic_call(A,B,C,D)).
+fill_expr_slots(unify(A,B,C,D,E), _, _, _, unify(A,B,C,D,E)).
+fill_expr_slots(pragma_foreign_code(A,B,C,D,E,F,G,H), _, _, _,
 		pragma_foreign_code(A,B,C,D,E,F,G,H)).
-fill_expr_slots(bi_implication(_, _), _, _, _) :-
+fill_expr_slots(bi_implication(_, _), _, _, _, _) :-
 	% these should have been expanded out by now
 	error("fill_expr_slots: unexpected bi_implication").
 
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.93
diff -u -r1.93 handle_options.m
--- compiler/handle_options.m	2000/10/03 00:34:08	1.93
+++ compiler/handle_options.m	2000/10/03 00:54:27
@@ -381,6 +381,12 @@
 		;
 			[]
 		),
+
+			% The following option allows us to perform retries
+			% from the middle of procedure bodies without requiring
+			% us to store everything on the nondet stack that may
+			% be hijacked being saved on entry to every procedure.
+		globals__io_set_option(allow_hijacks, bool(no)),
 			% The following option prevents useless variables
 			% from cluttering the trace. Its explicit setting
 			% removes a source of variability in the goal paths
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.77
diff -u -r1.77 hlds_goal.m
--- compiler/hlds_goal.m	2000/10/06 10:18:19	1.77
+++ compiler/hlds_goal.m	2000/10/10 00:04:30
@@ -652,8 +652,14 @@
 	--->	constraint	% This is included if the goal is
 				% a constraint.  See constraint.m
 				% for the definition of this.
-	    ;	(impure)	% This goal is impure.  See hlds_pred.m.
-	    ;	(semipure).	% This goal is semipure.  See hlds_pred.m.
+	;	(impure)	% This goal is impure.  See hlds_pred.m.
+	;	(semipure)	% This goal is semipure.  See hlds_pred.m.
+	;	call_table_gen.	% This goal generates the variable that
+				% represents the call table tip. If debugging
+				% is enabled, the code generator needs to save
+				% the value of this variable in its stack slot
+				% as soon as it is generated; this marker
+				% tells the code generator when this happens.
 
 	% see compiler/notes/allocation.html for what these alternatives mean
 :- type resume_point	--->	resume_point(set(prog_var), resume_locs)
@@ -685,9 +691,11 @@
 			;	ite_then
 			;	ite_else
 			;	neg
-			;	exist
+			;	exist(maybe_cut)
 			;	first
 			;	later.
+
+:- type maybe_cut	--->	cut ; no_cut.
 
 :- type goal_path == list(goal_path_step).
 
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.246
diff -u -r1.246 hlds_out.m
--- compiler/hlds_out.m	2000/10/06 10:18:20	1.246
+++ compiler/hlds_out.m	2000/10/09 00:57:38
@@ -2841,6 +2841,7 @@
 	{ proc_info_typeinfo_varmap(Proc, TypeInfoMap) },
 	{ proc_info_typeclass_info_varmap(Proc, TypeClassInfoMap) },
 	{ proc_info_is_address_taken(Proc, IsAddressTaken) },
+	{ proc_info_get_call_table_tip(Proc, MaybeCallTableTip) },
 	{ Indent1 is Indent + 1 },
 
 	hlds_out__write_indent(Indent1),
@@ -2885,6 +2886,14 @@
 		io__write_string("% address is taken\n")
 	;
 		io__write_string("% address is not taken\n")
+	),
+
+	( { MaybeCallTableTip = yes(CallTableTip) } ->
+		io__write_string("% call table tip: "),
+		mercury_output_var(CallTableTip, VarSet, AppendVarnums),
+		io__write_string("\n")
+	;
+		[]
 	),
 
 	hlds_out__write_indent(Indent),
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.83
diff -u -r1.83 hlds_pred.m
--- compiler/hlds_pred.m	2000/09/25 04:22:36	1.83
+++ compiler/hlds_pred.m	2000/10/04 05:19:27
@@ -1396,6 +1396,18 @@
 :- pred proc_info_set_rl_exprn_id(proc_info, rl_exprn_id, proc_info).
 :- mode proc_info_set_rl_exprn_id(in, in, out) is det.
 
+:- pred proc_info_get_need_maxfr_slot(proc_info, bool).
+:- mode proc_info_get_need_maxfr_slot(in, out) is det.
+
+:- pred proc_info_set_need_maxfr_slot(proc_info, bool, proc_info).
+:- mode proc_info_set_need_maxfr_slot(in, in, out) is det.
+
+:- pred proc_info_get_call_table_tip(proc_info, maybe(prog_var)).
+:- mode proc_info_get_call_table_tip(in, out) is det.
+
+:- pred proc_info_set_call_table_tip(proc_info, maybe(prog_var), proc_info).
+:- mode proc_info_set_call_table_tip(in, in, out) is det.
+
 	% For a set of variables V, find all the type variables in the types 
 	% of the variables in V, and return set of typeinfo variables for 
 	% those type variables. (find all typeinfos for variables in V).
@@ -1545,13 +1557,54 @@
 					% must be considered as having its
 					% address taken, since it is possible
 					% that some other module may do so.
-			maybe_aditi_rl_id :: maybe(rl_exprn_id)
+			maybe_aditi_rl_id :: maybe(rl_exprn_id),
 					% For predicates with an
 					% `aditi_top_down' marker, which are
 					% executed top-down on the Aditi side
 					% of the connection, we generate an RL
 					% expression, for which this is an
 					% identifier. See rl_update.m.
+ 			need_maxfr_slot	:: bool,
+					% True iff tracing is enabled, this
+ 					% is a procedure that lives on the det
+ 					% stack, and the code of this procedure
+ 					% may create a frame on the det stack.
+ 					% (Only in these circumstances do we
+ 					% need to reserve a stack slot to hold
+ 					% the value of maxfr at the call, for
+ 					% use in implementing retry.)
+ 					%
+ 					% This slot is used only with the LLDS
+					% backend XXX. Its value is set during
+					% the live_vars pass; it is invalid
+					% before then.
+ 			call_table_tip	:: maybe(prog_var)
+					% If the tracing is enabled and the
+ 					% procedure's evaluation method is
+ 					% memo, loopcheck or minimal, this
+ 					% slot identifies the variable that
+ 					% holds the tip of the call table.
+ 					% Otherwise, this field will be set to
+ 					% `no'.
+					%
+					% Tabled procedures record, in the
+					% data structure identified by this
+					% variable, that the call is active.
+					% When performing a retry across
+					% such a procedure, we must reset
+					% the state of the call; if we don't,
+					% the retried call will find the
+					% active call and report an infinite
+					% loop error.
+					%
+					% Such resetting of course requires
+					% the debugger to know whether the
+					% procedure has reached the call table
+					% tip yet. Therefore when binding this
+					% variable, the code generator of the
+					% relevant backend must record this
+					% fact in a place accessible to the
+					% debugger.
 		).
 
 	% Some parts of the procedure aren't known yet. We initialize
@@ -1581,7 +1634,7 @@
 		MaybeDet, BodyVarSet, BodyTypes, HeadVars, Modes, MaybeArgLives,
 		ClauseBody, MContext, StackSlots, InferredDet, CanProcess,
 		ArgInfo, InitialLiveness, TVarsMap, TCVarsMap, eval_normal,
-		no, no, DeclaredModes, IsAddressTaken, RLExprn
+		no, no, DeclaredModes, IsAddressTaken, RLExprn, no, no
 	).
 
 proc_info_set(DeclaredDetism, BodyVarSet, BodyTypes, HeadVars, HeadModes,
@@ -1593,7 +1646,7 @@
 		DeclaredDetism, BodyVarSet, BodyTypes, HeadVars, HeadModes,
 		HeadLives, Goal, Context, StackSlots, InferredDetism,
 		CanProcess, ArgInfo, Liveness, TVarMap, TCVarsMap, eval_normal, 
-		ArgSizes, Termination, no, IsAddressTaken, RLExprn).
+		ArgSizes, Termination, no, IsAddressTaken, RLExprn, no, no).
 
 proc_info_create(VarSet, VarTypes, HeadVars, HeadModes, Detism, Goal,
 		Context, TVarMap, TCVarsMap, IsAddressTaken, ProcInfo) :-
@@ -1604,7 +1657,7 @@
 	ProcInfo = procedure(yes(Detism), VarSet, VarTypes, HeadVars, HeadModes,
 		MaybeHeadLives, Goal, Context, StackSlots, Detism, yes, [],
 		Liveness, TVarMap, TCVarsMap, eval_normal, no, no, no, 
-		IsAddressTaken, RLExprn).
+		IsAddressTaken, RLExprn, no, no).
 
 proc_info_set_body(ProcInfo0, VarSet, VarTypes, HeadVars, Goal,
 		TI_VarMap, TCI_VarMap, ProcInfo) :-
@@ -1690,6 +1743,8 @@
 proc_info_maybe_declared_argmodes(ProcInfo, ProcInfo^maybe_declared_head_modes).
 proc_info_is_address_taken(ProcInfo, ProcInfo^is_address_taken).
 proc_info_get_rl_exprn_id(ProcInfo, ProcInfo^maybe_aditi_rl_id).
+proc_info_get_need_maxfr_slot(ProcInfo, ProcInfo^need_maxfr_slot).
+proc_info_get_call_table_tip(ProcInfo, ProcInfo^call_table_tip).
 
 proc_info_set_varset(ProcInfo, VS, ProcInfo^prog_varset := VS).
 proc_info_set_vartypes(ProcInfo, VT, ProcInfo^var_types := VT).
@@ -1715,6 +1770,8 @@
 	ProcInfo^maybe_termination := MT).
 proc_info_set_address_taken(ProcInfo, AT, ProcInfo^is_address_taken := AT).
 proc_info_set_rl_exprn_id(ProcInfo, ID, ProcInfo^maybe_aditi_rl_id := yes(ID)).
+proc_info_set_need_maxfr_slot(ProcInfo, NMS, ProcInfo^need_maxfr_slot := NMS).
+proc_info_set_call_table_tip(ProcInfo, CTT, ProcInfo^call_table_tip := CTT).
 
 proc_info_get_typeinfo_vars(Vars, VarTypes, TVarMap, TypeInfoVars) :-
 	set__to_sorted_list(Vars, VarList),
Index: compiler/jumpopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/jumpopt.m,v
retrieving revision 1.54
diff -u -r1.54 jumpopt.m
--- compiler/jumpopt.m	2000/10/03 00:34:10	1.54
+++ compiler/jumpopt.m	2000/10/03 00:54:27
@@ -242,7 +242,7 @@
 	string__append(Comment0, " (redirected return)", Redirect),
 	(
 		Uinstr0 = call(Proc, label(RetLabel), LiveInfos, Context,
-			CallModel)
+			GoalPath, CallModel)
 	->
 		(
 			% Look for det style tailcalls. We look for this
@@ -338,7 +338,8 @@
 				RemainInstrs = Instrs0
 			;
 				NewInstrs = [call(Proc, label(DestLabel),
-					LiveInfos, Context, CallModel)
+					LiveInfos, Context, GoalPath,
+					CallModel)
 					- Redirect],
 				RemainInstrs = Instrs0
 			),
Index: compiler/live_vars.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/live_vars.m,v
retrieving revision 1.92
diff -u -r1.92 live_vars.m
--- compiler/live_vars.m	2000/10/03 00:34:11	1.92
+++ compiler/live_vars.m	2000/10/04 05:21:01
@@ -63,20 +63,28 @@
 		set__init(ResumeVars0),
 		LiveSets1 = LiveSets0
 	),
-	trace__reserved_slots(ProcInfo0, Globals, NumReservedSlots),
+	trace__do_we_need_maxfr_slot(Globals, ProcInfo0, ProcInfo1),
+	trace__reserved_slots(ProcInfo1, Globals, NumReservedSlots,
+		MaybeReservedVarInfo),
+	( MaybeReservedVarInfo = yes(ResVar - _) ->
+		set__singleton_set(ResVarSet, ResVar),
+		set__insert(LiveSets1, ResVarSet, LiveSets2)
+	;
+		LiveSets2 = LiveSets1
+	),
 	module_info_pred_info(ModuleInfo, PredId, PredInfo),
 	body_should_use_typeinfo_liveness(PredInfo, Globals, TypeInfoLiveness),
-	AllocData = alloc_data(ModuleInfo, ProcInfo0, TypeInfoLiveness),
+	AllocData = alloc_data(ModuleInfo, ProcInfo1, TypeInfoLiveness),
 	set__init(NondetLiveness0),
 	build_live_sets_in_goal(Goal0, Liveness0,
-		NondetLiveness0, ResumeVars0, LiveSets1, AllocData,
+		NondetLiveness0, ResumeVars0, LiveSets2, AllocData,
 		_Liveness, _NondetLiveness, LiveSets),
 	graph_colour__group_elements(LiveSets, ColourSets),
 	set__to_sorted_list(ColourSets, ColourList),
 	allocate_stack_slots(ColourList, CodeModel, NumReservedSlots,
-		StackSlots),
+		MaybeReservedVarInfo, StackSlots),
 
-	proc_info_set_stack_slots(ProcInfo0, StackSlots, ProcInfo).
+	proc_info_set_stack_slots(ProcInfo1, StackSlots, ProcInfo).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -572,33 +580,42 @@
 %-----------------------------------------------------------------------------%
 
 :- pred allocate_stack_slots(list(set(prog_var))::in, code_model::in, int::in,
-	stack_slots::out) is det.
+	maybe(pair(prog_var, int))::in, stack_slots::out) is det.
 
-allocate_stack_slots(ColourList, CodeModel, NumReservedSlots, StackSlots) :-
+allocate_stack_slots(ColourList, CodeModel, NumReservedSlots,
+		MaybeReservedVarInfo, StackSlots) :-
 	map__init(StackSlots0),
 		% The reserved slots are referred to by fixed number
 		% (e.g. framevar(1)) in trace__setup.
 	FirstVarSlot is 1 + NumReservedSlots,
-	allocate_stack_slots_2(ColourList, FirstVarSlot, CodeModel,
-		StackSlots0, StackSlots).
+	allocate_stack_slots_2(ColourList, CodeModel, FirstVarSlot,
+		MaybeReservedVarInfo, StackSlots0, StackSlots).
 
-:- pred allocate_stack_slots_2(list(set(prog_var))::in, int::in, code_model::in,
+:- pred allocate_stack_slots_2(list(set(prog_var))::in, code_model::in,
+	int::in, maybe(pair(prog_var, int))::in,
 	stack_slots::in, stack_slots::out) is det.
 
-allocate_stack_slots_2([], _N, _CodeModel, StackSlots, StackSlots).
-allocate_stack_slots_2([Vars | VarSets], N0, CodeModel,
+allocate_stack_slots_2([], _, _, _, StackSlots, StackSlots).
+allocate_stack_slots_2([Vars | VarSets], CodeModel, N0, MaybeReservedVarInfo,
 		StackSlots0, StackSlots) :-
-	set__to_sorted_list(Vars, VarList),
 	(
-		CodeModel = model_non
+		MaybeReservedVarInfo = yes(ResVar - ResSlotNum),
+		set__member(ResVar, Vars)
 	->
-		Slot = framevar(N0)
+		SlotNum = ResSlotNum,
+		N1 = N0
 	;
-		Slot = stackvar(N0)
+		SlotNum = N0,
+		N1 = N0 + 1
 	),
+	( CodeModel = model_non ->
+		Slot = framevar(SlotNum)
+	;
+		Slot = stackvar(SlotNum)
+	),
+	set__to_sorted_list(Vars, VarList),
 	allocate_same_stack_slot(VarList, Slot, StackSlots0, StackSlots1),
-	N1 is N0 + 1,
-	allocate_stack_slots_2(VarSets, N1, CodeModel,
+	allocate_stack_slots_2(VarSets, CodeModel, N1, MaybeReservedVarInfo,
 		StackSlots1, StackSlots).
 
 :- pred allocate_same_stack_slot(list(prog_var)::in, lval::in, stack_slots::in,
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.49
diff -u -r1.49 livemap.m
--- compiler/livemap.m	2000/04/26 05:40:15	1.49
+++ compiler/livemap.m	2000/10/01 07:18:33
@@ -154,7 +154,7 @@
 		Instrs = Instrs0,
 		DontValueNumber = DontValueNumber0
 	;
-		Uinstr0 = call(_, _, _, _, _),
+		Uinstr0 = call(_, _, _, _, _, _),
 		livemap__look_for_livevals(Instrs0, Instrs,
 			Livevals0, Livevals, "call", yes, _),
 		Livemap = Livemap0,
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.265
diff -u -r1.265 llds.m
--- compiler/llds.m	2000/10/06 10:18:23	1.265
+++ compiler/llds.m	2000/10/09 00:57:39
@@ -16,7 +16,7 @@
 
 :- interface.
 
-:- import_module hlds_pred, hlds_data, tree, prog_data, (inst).
+:- import_module hlds_pred, hlds_goal, hlds_data, tree, prog_data, (inst).
 :- import_module rtti, builtin_ops.
 
 :- import_module bool, assoc_list, list, map, set, std_util, counter.
@@ -247,15 +247,18 @@
 			% specified by lval.
 
 	;	call(code_addr, code_addr, list(liveinfo), term__context,
-				call_model)
+				goal_path, call_model)
 			% call(Target, Continuation, _, _, _) is the same as
 			% succip = Continuation; goto(Target).
 			% The third argument is the live value info for the
 			% values live on return. The fourth argument gives
-			% the context of the call. The last gives the model
-			% of the called procedure, and if it is nondet,
-			% says whether tail recursion elimination is
-			% potentially applicable to the call.
+			% the context of the call. The fifth gives the goal
+			% path of the call in the body of the procedure; it is
+			% meaningful only if execution tracing is enabled.
+			% The last gives the code model of the called
+			% procedure, and if it is model_non, says whether
+			% tail recursion elimination is potentially applicable
+			% to the call.
 
 	;	mkframe(nondet_frame_info, code_addr)
 			% mkframe(NondetFrameInfo, CodeAddr) creates a nondet
@@ -1043,6 +1046,8 @@
 				% signed or unsigned
 				% (used for registers, stack slots, etc).
 
+:- func llds__stack_slot_num_to_lval(code_model, int) = lval.
+
 :- pred llds__wrap_rtti_data(rtti_data::in, comp_gen_c_data::out) is det.
 
 	% given a non-var rval, figure out its type
@@ -1076,6 +1081,13 @@
 :- implementation.
 
 :- import_module require.
+
+llds__stack_slot_num_to_lval(CodeModel, SlotNum) =
+	(if CodeModel = model_non then
+		framevar(SlotNum)
+	else
+		stackvar(SlotNum)
+	).
 
 llds__wrap_rtti_data(RttiData, rtti_data(RttiData)).
 
Index: compiler/llds_common.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_common.m,v
retrieving revision 1.33
diff -u -r1.33 llds_common.m
--- compiler/llds_common.m	2000/08/11 08:19:09	1.33
+++ compiler/llds_common.m	2000/10/01 07:18:33
@@ -174,7 +174,7 @@
 		llds_common__process_rval(Rval0, Rval, Info0, Info),
 		Instr = assign(Lval, Rval)
 	;
-		Instr0 = call(_, _, _, _, _),
+		Instr0 = call(_, _, _, _, _, _),
 		Instr = Instr0,
 		Info = Info0
 	;
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.157
diff -u -r1.157 llds_out.m
--- compiler/llds_out.m	2000/10/03 00:34:15	1.157
+++ compiler/llds_out.m	2000/10/03 00:54:28
@@ -1215,7 +1215,7 @@
 		:-
 	(
 		(
-			Instr = call(_, label(ContLabel), _, _, _)
+			Instr = call(_, label(ContLabel), _, _, _, _)
 		;
 			Instr = mkframe(_, label(ContLabel))
 		;
@@ -1319,7 +1319,8 @@
 output_instruction_decls(assign(Lval, Rval), DeclSet0, DeclSet) -->
 	output_lval_decls(Lval, "", "", 0, _, DeclSet0, DeclSet1),
 	output_rval_decls(Rval, "", "", 0, _, DeclSet1, DeclSet).
-output_instruction_decls(call(Target, ContLabel, _,_,_), DeclSet0, DeclSet) -->
+output_instruction_decls(call(Target, ContLabel, _, _, _, _),
+		DeclSet0, DeclSet) -->
 	output_code_addr_decls(Target, "", "", 0, _, DeclSet0, DeclSet1),
 	output_code_addr_decls(ContLabel, "", "", 0, _, DeclSet1, DeclSet).
 output_instruction_decls(c_code(_), DeclSet, DeclSet) --> [].
@@ -1581,7 +1582,7 @@
 	output_rval_as_type(Rval, Type),
 	io__write_string(";\n").
 
-output_instruction(call(Target, ContLabel, LiveVals, _, _), ProfInfo) -->
+output_instruction(call(Target, ContLabel, LiveVals, _, _, _), ProfInfo) -->
 	{ ProfInfo = CallerLabel - _ },
 	output_call(Target, ContLabel, CallerLabel),
 	output_gc_livevals(LiveVals).
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.84
diff -u -r1.84 middle_rec.m
--- compiler/middle_rec.m	2000/09/20 00:21:50	1.84
+++ compiler/middle_rec.m	2000/10/01 07:18:35
@@ -318,7 +318,7 @@
 middle_rec__split_rec_code([], _, _) :-
 	error("did not find call in middle_rec__split_rec_code").
 middle_rec__split_rec_code([Instr0 | Instrs1], Before, After) :-
-	( Instr0 = call(_, _, _, _, _) - _ ->
+	( Instr0 = call(_, _, _, _, _, _) - _ ->
 		(
 			opt_util__skip_comments(Instrs1, Instrs2),
 			Instrs2 = [Instr2 | Instrs3],
@@ -395,7 +395,7 @@
 middle_rec__find_used_registers_instr(assign(Lval, Rval), Used0, Used) :-
 	middle_rec__find_used_registers_lval(Lval, Used0, Used1),
 	middle_rec__find_used_registers_rval(Rval, Used1, Used).
-middle_rec__find_used_registers_instr(call(_, _, _, _, _), Used, Used).
+middle_rec__find_used_registers_instr(call(_, _, _, _, _, _), Used, Used).
 middle_rec__find_used_registers_instr(mkframe(_, _), Used, Used).
 middle_rec__find_used_registers_instr(label(_), Used, Used).
 middle_rec__find_used_registers_instr(goto(_), Used, Used).
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.106
diff -u -r1.106 opt_debug.m
--- compiler/opt_debug.m	2000/10/06 10:18:31	1.106
+++ compiler/opt_debug.m	2000/10/09 00:57:40
@@ -309,7 +309,7 @@
 
 opt_debug__dump_vninstr(vn_livevals(_), Str) :-
 	string__append_list(["livevals(...)"], Str).
-opt_debug__dump_vninstr(vn_call(Proc, Ret, _, _, _), Str) :-
+opt_debug__dump_vninstr(vn_call(Proc, Ret, _, _, _, _), Str) :-
 	opt_debug__dump_code_addr(Proc, P_str),
 	opt_debug__dump_code_addr(Ret, R_str),
 	string__append_list(["call(", P_str, ", ", R_str, ")"], Str).
@@ -932,7 +932,7 @@
 	opt_debug__dump_lval(Lval, L_str),
 	opt_debug__dump_rval(Rval, R_str),
 	string__append_list(["assign(", L_str, ", ", R_str, ")"], Str).
-opt_debug__dump_instr(call(Proc, Ret, _, _, _), Str) :-
+opt_debug__dump_instr(call(Proc, Ret, _, _, _, _), Str) :-
 	opt_debug__dump_code_addr(Proc, P_str),
 	opt_debug__dump_code_addr(Ret, R_str),
 	string__append_list(["call(", P_str, ", ", R_str, ", ...)"], Str).
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.109
diff -u -r1.109 opt_util.m
--- compiler/opt_util.m	2000/08/11 08:19:15	1.109
+++ compiler/opt_util.m	2000/10/01 07:18:36
@@ -780,7 +780,7 @@
 			opt_util__block_refers_stackvars(Instrs0, Need)
 		)
 	;
-		Uinstr0 = call(_, _, _, _, _),
+		Uinstr0 = call(_, _, _, _, _, _),
 		Need = no
 	;
 		Uinstr0 = mkframe(_, _),
@@ -983,7 +983,7 @@
 opt_util__can_instr_branch_away(livevals(_), no).
 opt_util__can_instr_branch_away(block(_, _, _), yes).
 opt_util__can_instr_branch_away(assign(_, _), no).
-opt_util__can_instr_branch_away(call(_, _, _, _, _), yes).
+opt_util__can_instr_branch_away(call(_, _, _, _, _, _), yes).
 opt_util__can_instr_branch_away(mkframe(_, _), no).
 opt_util__can_instr_branch_away(label(_), no).
 opt_util__can_instr_branch_away(goto(_), yes).
@@ -1050,7 +1050,7 @@
 opt_util__can_instr_fall_through(block(_, _, Instrs), FallThrough) :-
 	opt_util__can_block_fall_through(Instrs, FallThrough).
 opt_util__can_instr_fall_through(assign(_, _), yes).
-opt_util__can_instr_fall_through(call(_, _, _, _, _), no).
+opt_util__can_instr_fall_through(call(_, _, _, _, _, _), no).
 opt_util__can_instr_fall_through(mkframe(_, _), yes).
 opt_util__can_instr_fall_through(label(_), yes).
 opt_util__can_instr_fall_through(goto(_), no).
@@ -1096,7 +1096,7 @@
 opt_util__can_use_livevals(livevals(_), no).
 opt_util__can_use_livevals(block(_, _, _), no).
 opt_util__can_use_livevals(assign(_, _), no).
-opt_util__can_use_livevals(call(_, _, _, _, _), yes).
+opt_util__can_use_livevals(call(_, _, _, _, _, _), yes).
 opt_util__can_use_livevals(mkframe(_, _), no).
 opt_util__can_use_livevals(label(_), no).
 opt_util__can_use_livevals(goto(_), yes).
@@ -1159,7 +1159,7 @@
 opt_util__instr_labels_2(block(_, _, Instrs), Labels, CodeAddrs) :-
 	opt_util__instr_list_labels(Instrs, Labels, CodeAddrs).
 opt_util__instr_labels_2(assign(_,_), [], []).
-opt_util__instr_labels_2(call(Target, Ret, _, _, _), [], [Target, Ret]).
+opt_util__instr_labels_2(call(Target, Ret, _, _, _, _), [], [Target, Ret]).
 opt_util__instr_labels_2(mkframe(_, Addr), [], [Addr]).
 opt_util__instr_labels_2(label(_), [], []).
 opt_util__instr_labels_2(goto(Addr), [], [Addr]).
@@ -1192,7 +1192,7 @@
 opt_util__possible_targets(block(_, _, _), _) :-
 	error("block in possible_targets").
 opt_util__possible_targets(assign(_, _), []).
-opt_util__possible_targets(call(_, ReturnAddr, _, _, _), Labels) :-
+opt_util__possible_targets(call(_, ReturnAddr, _, _, _, _), Labels) :-
 	( ReturnAddr = label(Label) ->
 		Labels = [Label]
 	;
@@ -1267,7 +1267,7 @@
 opt_util__instr_rvals_and_lvals(block(_, _, Instrs), Labels, CodeAddrs) :-
 	opt_util__instr_list_rvals_and_lvals(Instrs, Labels, CodeAddrs).
 opt_util__instr_rvals_and_lvals(assign(Lval,Rval), [Rval], [Lval]).
-opt_util__instr_rvals_and_lvals(call(_, _, _, _, _), [], []).
+opt_util__instr_rvals_and_lvals(call(_, _, _, _, _, _), [], []).
 opt_util__instr_rvals_and_lvals(mkframe(_, _), [], []).
 opt_util__instr_rvals_and_lvals(label(_), [], []).
 opt_util__instr_rvals_and_lvals(goto(_), [], []).
@@ -1402,7 +1402,7 @@
 opt_util__count_temps_instr(assign(Lval, Rval), R0, R, F0, F) :-
 	opt_util__count_temps_lval(Lval, R0, R1, F0, F1),
 	opt_util__count_temps_rval(Rval, R1, R, F1, F).
-opt_util__count_temps_instr(call(_, _, _, _, _), R, R, F, F).
+opt_util__count_temps_instr(call(_, _, _, _, _, _), R, R, F, F).
 opt_util__count_temps_instr(mkframe(_, _), R, R, F, F).
 opt_util__count_temps_instr(label(_), R, R, F, F).
 opt_util__count_temps_instr(goto(_), R, R, F, F).
@@ -1756,8 +1756,8 @@
 		Lval = Lval0,
 		Rval = Rval0
 	).
-opt_util__replace_labels_instr(call(Target, Return0, LiveInfo, Context, CM),
-		ReplMap, _, call(Target, Return, LiveInfo, Context, CM)) :-
+opt_util__replace_labels_instr(call(Target, Return0, LiveInfo, CXT, GP, CM),
+		ReplMap, _, call(Target, Return, LiveInfo, CXT, GP, CM)) :-
 	opt_util__replace_labels_code_addr(Return0, ReplMap, Return).
 opt_util__replace_labels_instr(mkframe(NondetFrameInfo, Redoip0), ReplMap,
 		ReplData, mkframe(NondetFrameInfo, Redoip)) :-
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.53
diff -u -r1.53 stack_layout.m
--- compiler/stack_layout.m	2000/10/03 00:34:27	1.53
+++ compiler/stack_layout.m	2000/10/09 02:48:06
@@ -21,85 +21,94 @@
 %
 %---------------------------------------------------------------------------%
 %
-% Data Stucture: stack_layouts
+% Data Structure: procedure layouts
 %
 % If the option basic_stack_layout is set, we generate a MR_Stack_Layout_Entry
 % for each procedure. This will be stored in the global variable whose name is
 %	mercury_data__layout__mercury__<proc_label>.
-% This structure will always contain stack tracing information:
 %
-%	code address		(Code *) - address of entry
-% 	succip stack location	(uint_least32_t) actually, type MR_Long_Lval
-% 					(the location will be set to -1
-% 					if there is no succip available).
-% 	number of stack slots	(uint_least16_t)
-% 	determinism		(uint_least16_t) actually, type MR_Determinism
-%
-% If the option procid_stack_layout is set, i.e. if we are doing stack
-% tracing, execution tracing or profiling, the structure will also include
-% information on the identity of the procedure. This information will take
-% one of two forms. Almost all procedures use the first form:
-%
-%	predicate/function	(Integer) actually, MR_pred_func
-%	declaring module name	(String)
-%	defining module name	(String)
-%	predicate name		(String)
-%	predicate arity		(int_least16_t)
-%	procedure number	(int_least16_t)
-%
-% Automatically generated unification, index and comparison predicates
-% use the second form:
-%
-%	type name		(String)
-%	type module's name	(String)
-%	defining module name	(String)
-%	predicate name		(String)
-%	predicate arity		(int_least16_t)
-%	procedure number	(int_least16_t)
-%
-% The runtime system can figure out which form is present by testing
-% the value of the first slot. A value of 0 or 1 indicates the first form;
-% any higher value indicates the second form. The distinguished value -1
-% indicates that procid_stack_layout is not set, and that the later fields
-% are not present.
-%
-% The meanings of the fields in both forms are the same as in procedure labels.
-%
-% If the option trace_stack_layout is set, i.e. if we are doing execution
-% tracing, the structure will also include some extra fields:
-%
-%	call trace info		(MR_Stack_Layout_Label *) - points to the
-%				layout structure of the call event
-%	module layout		(MR_Module_Layout *) - points to the layout
-%				struct of the containing module.
-%	variable names		(int_least16_t *) - pointer to an array of
-%				offsets into the module-wide string table
-%	variable name count	(int_least16_t) - the number of offsets in the
-%				variable names array
-%	max reg at trace event	(int_least16_t) - the number of the highest
-%				numbered rN register live at a trace event
-%				inside the procedure
-%	maybe from full		(int_least8_t) - number of the stack slot of
-%				the from_full flag, if the procedure is
-%				shallow traced
-%	maybe trail		(int_least8_t) - number of the first of two
-%				stack slots used for recording the state of
-%				the trail, if trailing is enabled
-%	maybe decl debug	(int_least8_t) - number of the first of two
-%				stack slots used by the declarative debugger,
-%				if --trace-decl is set
-%
-% The call trace info field will point to the label layout structure for the
-% label associated with the call event at the entry to the procedure. The
-% purpose of this information is to allow the runtime debugger to find out
-% which variables are where on entry, so it can reexecute the procedure if
-% asked to do so and if the values of the required variables are still
-% available. (If trace_stack_layout is not set, this field will be present,
-% but it will be set to NULL.)
-%
-% The module layout field will point to the layout structure of the entire
-% module. Amongst other things, the string table for the module is stored
-% there. The variable names field points to an array that contains offsets
+% This structure contains up to three groups of fields. The first group,
+% which contains information that enables the stack to be traversed, is always
+% present. The second group, which identifies the procedure in terms that are
+% meaningful to both humans and machines, will be generated only if the option
+% procid_stack_layout is set, i.e. if we are doing stack tracing, execution
+% tracing or profiling. The third group, which contains information
+% specifically intended for the debugger, will be generated only if the option
+% trace_stack_layout is set.
+%
+% The distinguished value -1 in the first field of the second group
+% indicates that the later fields are not present.
+%
+% The distinguished value NULL in the first field of the third group
+% indicates that the later fields are not present.
+%
+%---------------------------------------------------------------------------%
+%
+% The first group contains the following fields:
+%
+%	MR_Code			*MR_sle_code_addr;
+%	MR_Long_Lval		MR_sle_succip_locn;
+%	MR_int_least16_t	MR_sle_stack_slots;
+%	MR_Determinism		MR_sle_detism;
+%
+% The code_addr field points to the start of the procedure's code.
+%
+% The succip_locn field encoded the location of the saved succip if it is saved
+% in a general purpose stack slot. If the succip is saved in a specal purpose
+% stack slot (as it is for model_non procedures) or if the procedure never
+% saves the succip (as in leaf procedures), this field will contain -1.
+%
+% The stack_slots field gives the number of general purpose stack slots
+% in the procedure.
+%
+% The detism field encodes the determinism of the procedure.
+%
+%---------------------------------------------------------------------------%
+%
+% The second group contains one field:
+%
+%	MR_Stack_Layout_Proc_Id	MR_sle_proc_id;
+%
+% This field is a union. The usual alternative of which identifies ordinary
+% procedures, while the other alternative identifies automatically generated 
+% unification, comparison and index functions. The meanings of the fields
+% in both forms are the same as in procedure labels. The runtime system can
+% figure out which form is present by testing the value of the first slot,
+% as the acceptable ranges of values of the first fields (which are the same
+% size) are disjoint.
+%
+%---------------------------------------------------------------------------%
+%
+% The third group contains the following fields:
+%
+%	struct MR_Stack_Layout_Label_Struct	*MR_sle_call_label;
+%	struct MR_Module_Layout_Struct		*MR_sle_module_layout;
+%	MR_Word					MR_sle_proc_rep;
+%	MR_int_least16_t			*MR_sle_used_var_names;
+%	MR_int_least16_t			MR_sle_max_var_num;
+%	MR_int_least16_t			MR_sle_max_r_num;
+%	MR_int_least8_t				MR_sle_maybe_from_full;
+%	MR_int_least8_t				MR_sle_maybe_trail;
+%	MR_int_least8_t				MR_sle_maybe_maxfr;
+%	MR_EvalMethod				MR_sle_eval_method:8;
+%	MR_int_least8_t				MR_sle_maybe_call_table;
+%	MR_int_least8_t				MR_sle_maybe_decl_debug;
+%
+% The call_label field points to the label layout structure for the label
+% associated with the call event at the entry to the procedure. The purpose
+% of this field is to allow the runtime debugger to find out which variables
+% are where on entry, so it can reexecute the procedure if asked to do so
+% and if the values of the required variables are still available.
+%
+% The module_layout field points to the module info structure of the module
+% containing the procedure. This allows the debugger access to the string table
+% stored there, as well the table associating source-file contexts with labels.
+%
+% The proc_rep field contains a representation of the body of the procedure
+% as a Mercury term of type goal_rep, defined in program_representation.m.
+% If will be 0 if no such representation is available.
+%
+% The used_var_names field points to an array that contains offsets
 % into the string table, with the offset at index i-1 giving the name of
 % variable i (since variable numbers start at one). If a variable has no name
 % or cannot be referred to from an event, the offset will be zero, at which
@@ -111,19 +120,52 @@
 % Therefore using the stored offset to index into the string table
 % is always safe.
 %
-% If the procedure is compiled with deep tracing, the from full field will
-% contain a negative number. If it is compiled with shallow tracing, it will
-% contain the number of the stack slot that holds the flag that says whether
-% this incarnation of the procedure was called from deeply traced code or not.
-% (The determinism of the procedure decides whether the stack slot refers
-% to a stackvar or a framevar.)
-%
-% If --trace-decl is not set, the maybe decl debug field will contain a
-% negative number. If it is set, it will contain the number of the first
-% of two stack slots used by the declarative debugger; the other slot is
-% the next higher numbered one. (The determinism of the procedure decides
-% whether the stack slot refers to a stackvar or a framevar.)
+% The max_var_num field gives the number of elements in the used_var_names
+% table.
 %
+% The max_r_num field tells the debugger which Mercury abstract machine
+% registers need saving in MR_trace: besides the special registers, it is
+% the general-purpose registers rN for values of N up to and including the
+% value of this field. Note that this field contains an upper bound; in
+% general, there will be calls to MR_trace at which the number of the highest
+% numbered general purpose (i.e. rN) registers is less than this. However,
+% storing the upper bound gets us almost all the benefit (of not saving and
+% restoring all the thousand rN registers) for a small fraction of the static
+% space cost of storing the actual number in label layout structures.
+%
+% If the procedure is compiled with deep tracing, the maybe_from_full field
+% will contain a negative number. If it is compiled with shallow tracing,
+% it will contain the number of the stack slot that holds the flag that says
+% whether this incarnation of the procedure was called from deeply traced code
+% or not. (The determinism of the procedure decides whether the stack slot
+% refers to a stackvar or a framevar.)
+%
+% If trailing is not enabled, the maybe_trail field will contain a negative
+% number. If it is enabled, it will contain number of the first of two stack
+% slots used for checkpointing the state of the trail on entry to the
+% procedure. The first contains the trail pointer, the second the ticket.
+%
+% If the procedure lives on the nondet stack, or if it cannot create any
+% temporary nondet stack frames, the maybe_maxfr field will contain a negative
+% number. If it lives on the det stack, and can create temporary nondet stack
+% frames, it will contain the number number of the stack slot that contains the
+% value of maxfr on entry, for use in executing the retry debugger command
+% from the middle of the procedure.
+%
+% The eval_method field contains a representation of the evaluation method
+% used by the procedure. The retry command needs this information if it is
+% to reset the call tables of the procedure invocations being retried.
+%
+% If --trace-decl is not set, the maybe_decl field will contain a negative
+% number. If it is set, it will contain the number of the first of two stack
+% slots used by the declarative debugger; the other slot is the next higher
+% numbered one. (The determinism of the procedure decides whether the stack
+% slot refers to a stackvar or a framevar.)
+%
+%---------------------------------------------------------------------------%
+%
+% Data Structure: label layouts
+%
 % If the option basic_stack_layout is set, we generate stack layout tables
 % for some labels internal to the procedure. This table will be stored in the
 % global variable whose name is
@@ -549,8 +591,8 @@
 	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__construct_layouts(ProcLayoutInfo) -->
-	{ ProcLayoutInfo = proc_layout_info(EntryLabel, Detism,
-		StackSlots, SuccipLoc, MaybeCallLabel, MaxTraceReg,
+	{ ProcLayoutInfo = proc_layout_info(EntryLabel, Detism, StackSlots,
+		SuccipLoc, EvalMethod, MaybeCallLabel, MaxTraceReg,
 		Goal, InstMap, TraceSlotInfo, ForceProcIdLayout,
 		VarSet, InternalMap) },
 	{ map__to_assoc_list(InternalMap, Internals) },
@@ -562,8 +604,8 @@
 	{ list__foldl(stack_layout__update_label_table, Internals,
 		LabelTables0, LabelTables) },
 	stack_layout__set_label_tables(LabelTables),
-	stack_layout__construct_proc_layout(EntryLabel, Detism,
-		StackSlots, SuccipLoc, MaybeCallLabel, MaxTraceReg,
+	stack_layout__construct_proc_layout(EntryLabel, Detism, StackSlots,
+		SuccipLoc, EvalMethod, MaybeCallLabel, MaxTraceReg,
 		Goal, InstMap, TraceSlotInfo, ForceProcIdLayout,
 		VarSet, NamedVars).
 
@@ -580,7 +622,7 @@
 	(
 		Return = yes(return_layout_info(TargetsContexts, _)),
 		stack_layout__find_valid_return_context(TargetsContexts,
-			Target, Context)
+			Target, Context, _GoalPath)
 	->
 		( Target = label(TargetLabel) ->
 			IsReturn = known_callee(TargetLabel)
@@ -633,17 +675,18 @@
 	).
 
 :- pred stack_layout__find_valid_return_context(
-	assoc_list(code_addr, prog_context)::in,
-	code_addr::out, prog_context::out) is semidet.
+	assoc_list(code_addr, pair(prog_context, goal_path))::in,
+	code_addr::out, prog_context::out, goal_path::out) is semidet.
 
-stack_layout__find_valid_return_context([Target - Context | TargetContexts],
-		ValidTarget, ValidContext) :-
+stack_layout__find_valid_return_context([Target - (Context - GoalPath)
+		| TargetContexts], ValidTarget, ValidContext, ValidGoalPath) :-
 	( stack_layout__context_is_valid(Context) ->
 		ValidTarget = Target,
-		ValidContext = Context
+		ValidContext = Context,
+		ValidGoalPath = GoalPath
 	;
 		stack_layout__find_valid_return_context(TargetContexts,
-			ValidTarget, ValidContext)
+			ValidTarget, ValidContext, ValidGoalPath)
 	).
 
 :- pred stack_layout__context_is_valid(prog_context::in) is semidet.
@@ -659,14 +702,15 @@
 	% Construct a procedure-specific layout.
 
 :- pred stack_layout__construct_proc_layout(label::in, determinism::in,
-	int::in, maybe(int)::in, maybe(label)::in, int::in,
-	hlds_goal::in, instmap::in, trace_slot_info::in, bool::in,
+	int::in, maybe(int)::in, eval_method::in, maybe(label)::in,
+	int::in, hlds_goal::in, instmap::in, trace_slot_info::in, bool::in,
 	prog_varset::in, map(int, string)::in,
 	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__construct_proc_layout(EntryLabel, Detism, StackSlots,
-		MaybeSuccipLoc, MaybeCallLabel, MaxTraceReg, Goal, InstMap,
-		TraceSlotInfo, ForceProcIdLayout, VarSet, UsedVarNames) -->
+		MaybeSuccipLoc, EvalMethod, MaybeCallLabel, MaxTraceReg,
+		Goal, InstMap, TraceSlotInfo, ForceProcIdLayout,
+		VarSet, UsedVarNames) -->
 	{
 		MaybeSuccipLoc = yes(Location0)
 	->
@@ -728,9 +772,10 @@
 			ProcLabel) },
 		{ stack_layout__construct_procid_rvals(ProcLabel, IdRvals,
 			IdArgTypes) },
-		stack_layout__construct_trace_layout(MaybeCallLabel,
-			MaxTraceReg, Goal, InstMap, TraceSlotInfo,
-			VarSet, UsedVarNames, TraceRvals, TraceArgTypes),
+		stack_layout__construct_trace_layout(EvalMethod,
+			MaybeCallLabel, MaxTraceReg, Goal, InstMap,
+			TraceSlotInfo, VarSet, UsedVarNames,
+			TraceRvals, TraceArgTypes),
 		{ list__append(IdRvals, TraceRvals, IdTraceRvals) },
 		{ IdTraceArgTypes = initial(IdArgTypes, TraceArgTypes) }
 	;
@@ -752,13 +797,13 @@
 		Rvals, ArgTypes, []) },
 	stack_layout__add_proc_layout_data(CData, CDataName, EntryLabel).
 
-:- pred stack_layout__construct_trace_layout(maybe(label)::in, int::in,
-	hlds_goal::in, instmap::in, trace_slot_info::in,
-	prog_varset::in, map(int, string)::in,
+:- pred stack_layout__construct_trace_layout(eval_method::in,
+	maybe(label)::in, int::in, hlds_goal::in, instmap::in,
+	trace_slot_info::in, prog_varset::in, map(int, string)::in,
 	list(maybe(rval))::out, create_arg_types::out,
 	stack_layout_info::in, stack_layout_info::out) is det.
 
-stack_layout__construct_trace_layout(MaybeCallLabel, MaxTraceReg,
+stack_layout__construct_trace_layout(EvalMethod, MaybeCallLabel, MaxTraceReg,
 		Goal, InstMap, TraceSlotInfo, VarSet, UsedVarNameMap,
 		Rvals, ArgTypes) -->
 	stack_layout__get_trace_stack_layout(TraceLayout),
@@ -797,29 +842,44 @@
 				data_addr(ModuleName, module_layout)))),
 		MaxTraceRegRval = yes(const(int_const(MaxTraceReg))),
 		TraceSlotInfo = trace_slot_info(MaybeFromFullSlot,
-			MaybeDeclSlots, MaybeTrailSlot),
+			MaybeDeclSlots, MaybeTrailSlots, MaybeMaxfrSlot,
+			MaybeCallTableSlot),
+		EvalMethodInt =
+			stack_layout__represent_eval_method(EvalMethod),
+		EvalMethodRval = yes(const(int_const(EvalMethodInt))),
 		( MaybeFromFullSlot = yes(FromFullSlot) ->
 			FromFullRval = yes(const(int_const(FromFullSlot)))
 		;
 			FromFullRval = yes(const(int_const(-1)))
 		),
+		( MaybeTrailSlots = yes(FirstTrailSlot) ->
+			TrailRval = yes(const(int_const(FirstTrailSlot)))
+		;
+			TrailRval = yes(const(int_const(-1)))
+		),
+		( MaybeMaxfrSlot = yes(MaxfrSlot) ->
+			MaxfrRval = yes(const(int_const(MaxfrSlot)))
+		;
+			MaxfrRval = yes(const(int_const(-1)))
+		),
+		( MaybeCallTableSlot = yes(CallTableSlot) ->
+			CallTableRval = yes(const(int_const(CallTableSlot)))
+		;
+			CallTableRval = yes(const(int_const(-1)))
+		),
 		( MaybeDeclSlots = yes(DeclSlot) ->
 			DeclRval = yes(const(int_const(DeclSlot)))
 		;
 			DeclRval = yes(const(int_const(-1)))
 		),
-		( MaybeTrailSlot = yes(TrailSlot) ->
-			TrailRval = yes(const(int_const(TrailSlot)))
-		;
-			TrailRval = yes(const(int_const(-1)))
-		),
 		Rvals = [CallRval, ModuleRval, GoalRepRval, VarNameVector,
 			VarNameCount, MaxTraceRegRval,
-			FromFullRval, TrailRval, DeclRval],
+			FromFullRval, TrailRval, MaxfrRval,
+			EvalMethodRval, CallTableRval, DeclRval],
 		ArgTypes = initial([
 			4 - yes(data_ptr),
 			2 - yes(int_least16),
-			3 - yes(int_least8)],
+			6 - yes(int_least8)],
 			none)
 		}
 	;
@@ -828,6 +888,14 @@
 		{ ArgTypes = initial([1 - yes(integer)], none) }
 	).
 
+:- func stack_layout__represent_eval_method(eval_method) = int.
+
+stack_layout__represent_eval_method(eval_normal)     = 0.
+stack_layout__represent_eval_method(eval_loop_check) = 1.
+stack_layout__represent_eval_method(eval_memo)       = 2.
+stack_layout__represent_eval_method(eval_minimal)    = 3.
+
+
 :- pred stack_layout__construct_var_name_vector(prog_varset::in,
 	map(int, string)::in, maybe(rval)::out, maybe(rval)::out,
 	stack_layout_info::in, stack_layout_info::out) is det.
@@ -907,7 +975,8 @@
 				yes(const(int_const(Arity))),
 				yes(const(int_const(Mode)))
 			],
-		ArgTypes = [4 - no, 2 - yes(int_least16)]
+		ArgTypes = [1 - yes(integer), 3 - yes(string),
+				2 - yes(int_least16)]
 	;
 		ProcLabel = special_proc(DefModule, PredName, TypeModule,
 			TypeName, Arity, ProcId),
@@ -922,7 +991,7 @@
 				yes(const(int_const(Arity))),
 				yes(const(int_const(Mode)))
 			],
-		ArgTypes = [4 - no, 2 - yes(int_least16)]
+		ArgTypes = [4 - yes(string), 2 - yes(int_least16)]
 	).
 
 :- pred stack_layout__represent_pred_or_func(pred_or_func::in, int::out) is det.
@@ -979,30 +1048,51 @@
 			ResumeTypeVarMap)
 	},
 	(
-		{ Trace = yes(trace_port_layout_info(_, Port, Path, _)) },
+		{ Trace = yes(trace_port_layout_info(_, Port, GoalPath, _)) },
 		{ Return = no },
 		{ llds_out__trace_port_to_num(Port, PortNum) },
-		{ trace__path_to_string(Path, PathStr) },
-		stack_layout__lookup_string_in_table(PathStr, PathNum)
+		{ trace__path_to_string(GoalPath, GoalPathStr) },
+		stack_layout__lookup_string_in_table(GoalPathStr, GoalPathNum)
 	;
 		{ Trace = no },
-		{ Return = yes(_) },
-			% We only ever use the port and path fields of these
-			% layout structures when we process exception events.
+		{ Return = yes(ReturnInfo) },
+			% We only ever use the port fields of these layout
+			% structures when we process exception events.
+			% (Since exception events are interface events,
+			% the goal path field is not meaningful then.)
 		{ llds_out__trace_port_to_num(exception, PortNum) },
-		{ PathNum = 0 }
+			% We only ever use the goal path fields of these
+			% layout structures when we process "fail" commands
+			% in the debugger.
+		{ ReturnInfo = return_layout_info(TargetsContexts, _) },
+		(
+			{ stack_layout__find_valid_return_context(
+				TargetsContexts, _, _, GoalPath) }
+		->
+			{ trace__path_to_string(GoalPath, GoalPathStr) },
+			stack_layout__lookup_string_in_table(GoalPathStr,
+				GoalPathNum)
+		;
+				% If tracing is enabled, then exactly one of
+				% the calls for which this label is a return
+				% site would have had a valid context. If none
+				% do, then tracing is not enabled, and
+				% therefore the goal path of this label will
+				% not be accessed.
+			{ GoalPathNum = 0 }
+		)
 	;
 		{ Trace = no },
 		{ Return = no },
 		{ PortNum = -1 },
-		{ PathNum = -1 }
+		{ GoalPathNum = -1 }
 	;
 		{ Trace = yes(_) },
 		{ Return = yes(_) },
 		{ error("label has both trace and return layout info") }
 	),
 	{ TraceRvals = [yes(const(int_const(PortNum))),
-			yes(const(int_const(PathNum)))] },
+			yes(const(int_const(GoalPathNum)))] },
 	stack_layout__get_agc_stack_layout(AgcStackLayout),
 	{
 		Return = no,
Index: compiler/table_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/table_gen.m,v
retrieving revision 1.23
diff -u -r1.23 table_gen.m
--- compiler/table_gen.m	2000/09/20 12:12:09	1.23
+++ compiler/table_gen.m	2000/10/04 05:27:48
@@ -255,19 +255,22 @@
 		table_gen__create_new_det_goal(EvalMethod, Detism, OrigGoal,
 			PredId, ProcId, HeadVars, ArgModes,
 			VarTypes0, VarTypes, VarSet0, VarSet,
-			TableInfo0, TableInfo, Goal)
+			TableInfo0, TableInfo, CallTableTip, Goal),
+		MaybeCallTableTip = yes(CallTableTip)
 	;
 		CodeModel = model_semi,
 		table_gen__create_new_semi_goal(EvalMethod, Detism, OrigGoal,
 			PredId, ProcId, HeadVars, ArgModes,
 			VarTypes0, VarTypes, VarSet0, VarSet,
-			TableInfo0, TableInfo, Goal)
+			TableInfo0, TableInfo, CallTableTip, Goal),
+		MaybeCallTableTip = yes(CallTableTip)
 	;
 		CodeModel = model_non,
 		table_gen__create_new_non_goal(EvalMethod, Detism, OrigGoal,
 			PredId, ProcId, HeadVars, ArgModes,
 			VarTypes0, VarTypes, VarSet0, VarSet,
-			TableInfo0, TableInfo, Goal)
+			TableInfo0, TableInfo, CallTableTip, Goal),
+		MaybeCallTableTip = yes(CallTableTip)
 	),
 
 	table_info_extract(TableInfo, Module1, PredInfo1, ProcInfo1),
@@ -277,12 +280,13 @@
 	proc_info_set_goal(ProcInfo1, Goal, ProcInfo2),
 	proc_info_set_varset(ProcInfo2, VarSet, ProcInfo3),
 	proc_info_set_vartypes(ProcInfo3, VarTypes, ProcInfo4),
+	proc_info_set_call_table_tip(ProcInfo4, MaybeCallTableTip, ProcInfo5),
 
 	% Some of the instmap_deltas generated in this module
 	% are pretty dodgy (especially those for if-then-elses), so 
 	% recompute them here.
 	RecomputeAtomic = no,
-	recompute_instmap_delta_proc(RecomputeAtomic, ProcInfo4, ProcInfo,
+	recompute_instmap_delta_proc(RecomputeAtomic, ProcInfo5, ProcInfo,
 		Module1, Module2),
 
 	pred_info_procedures(PredInfo1, ProcTable1),
@@ -301,11 +305,11 @@
 	hlds_goal::in, pred_id::in, proc_id::in, list(prog_var)::in,
 	list(mode)::in, map(prog_var, type)::in, map(prog_var, type)::out,
 	prog_varset::in, prog_varset::out, table_info::in, table_info::out,
-	hlds_goal::out) is det.
+	prog_var::out, hlds_goal::out) is det.
 
 table_gen__create_new_det_goal(EvalMethod, Detism, OrigGoal, PredId, ProcId,
 		HeadVars, HeadVarModes, VarTypes0, VarTypes,
-		VarSet0, VarSet, TableInfo0, TableInfo, Goal) :-
+		VarSet0, VarSet, TableInfo0, TableInfo, TableVar, Goal) :-
 	% even if the original goal doesn't use all of the headvars,
 	% the code generated by the tabling transformation does,
 	% so we need to compute the nonlocals from the headvars rather
@@ -320,7 +324,7 @@
 	get_input_output_vars(HeadVars, HeadVarModes, Module, InputVars,
 		OutputVars),
 
-	generate_det_lookup_goal(InputVars, PredId, ProcId, Context,
+	generate_simple_lookup_goal(InputVars, PredId, ProcId, Context,
 		VarTypes0, VarTypes1, VarSet0, VarSet1, TableInfo0, TableInfo1,
 		TableVar, LookUpGoal),
 	generate_call("table_simple_is_complete", [TableVar], semidet,
@@ -406,11 +410,11 @@
 	hlds_goal::in, pred_id::in, proc_id::in, list(prog_var)::in,
 	list(mode)::in, map(prog_var, type)::in, map(prog_var, type)::out,
 	prog_varset::in, prog_varset::out, table_info::in, table_info::out,
-	hlds_goal::out) is det.
+	prog_var::out, hlds_goal::out) is det.
 
 table_gen__create_new_semi_goal(EvalMethod, Detism, OrigGoal, PredId, ProcId,
 		HeadVars, HeadVarModes, VarTypes0, VarTypes,
-		VarSet0, VarSet, TableInfo0, TableInfo, Goal) :-
+		VarSet0, VarSet, TableInfo0, TableInfo, TableVar, Goal) :-
 	% even if the original goal doesn't use all of the headvars,
 	% the code generated by the tabling transformation does,
 	% so we need to compute the nonlocals from the headvars rather
@@ -424,7 +428,7 @@
 	get_input_output_vars(HeadVars, HeadVarModes, Module, InputVars,
 		OutputVars),
 
-	generate_det_lookup_goal(InputVars, PredId, ProcId, Context,
+	generate_simple_lookup_goal(InputVars, PredId, ProcId, Context,
 		VarTypes0, VarTypes1, VarSet0, VarSet1, TableInfo0, TableInfo1,
 		TableVar, LookUpGoal),
 	generate_call("table_simple_is_complete", [TableVar],
@@ -573,11 +577,11 @@
 	hlds_goal::in, pred_id::in, proc_id::in, list(prog_var)::in,
 	list(mode)::in, map(prog_var, type)::in, map(prog_var, type)::out,
 	prog_varset::in, prog_varset::out, table_info::in, table_info::out,
-	hlds_goal::out) is det.
+	prog_var::out, hlds_goal::out) is det.
 
 table_gen__create_new_non_goal(EvalMethod, Detism, OrigGoal, PredId, ProcId,
 		HeadVars, HeadVarModes, VarTypes0, VarTypes,
-		VarSet0, VarSet, TableInfo0, TableInfo, Goal) :-
+		VarSet0, VarSet, TableInfo0, TableInfo, TableVar, Goal) :-
 	% even if the original goal doesn't use all of the headvars,
 	% the code generated by the tabling transformation does,
 	% so we need to compute the nonlocals from the headvars rather
@@ -613,6 +617,9 @@
 		[], Module, Context, ResumeGoal0),
 	append_fail(ResumeGoal0, ResumeGoal1),
 
+	true_goal(TrueGoal),
+	fail_goal(FailGoal),
+
 	map__init(StoreMap),
 	(
 		EvalMethod = eval_memo
@@ -622,7 +629,6 @@
 	;
 		EvalMethod = eval_loop_check
 	->
-		true_goal(TrueGoal),
 		SaveAnsGoal = TrueGoal,
 		ActiveGoal = LoopErrorGoal
 	;
@@ -632,7 +638,7 @@
 		ActiveGoal = SuspendGoal
 	;
 		error(
-    "table_gen__create_new_non_goal: unsupported evaluation model")
+		"table_gen__create_new_non_goal: unsupported evaluation model")
 	),
 
 	GenAnsGoalPart1Ex = conj([MarkAsActiveGoal, OrigGoal, SaveAnsGoal]),
@@ -650,7 +656,6 @@
 	->
 		ResumeGoal = ResumeGoal1
 	;
-		fail_goal(FailGoal),
 		ResumeGoal = FailGoal
 	),
 	GenAnsGoalEx = disj([GenAnsGoalPart1, ResumeGoal], StoreMap),
@@ -694,12 +699,13 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred generate_det_lookup_goal(list(prog_var)::in, pred_id::in, proc_id::in,
-	term__context::in, map(prog_var, type)::in, map(prog_var, type)::out,
+:- pred generate_simple_lookup_goal(list(prog_var)::in,
+	pred_id::in, proc_id::in, term__context::in,
+	map(prog_var, type)::in, map(prog_var, type)::out,
 	prog_varset::in, prog_varset::out, table_info::in, table_info::out,
 	prog_var::out, hlds_goal::out) is det.
 
-generate_det_lookup_goal(Vars, PredId, ProcId, Context, VarTypes0, VarTypes,
+generate_simple_lookup_goal(Vars, PredId, ProcId, Context, VarTypes0, VarTypes,
 		VarSet0, VarSet, TableInfo0, TableInfo, TableVar, Goal) :-
 
 	generate_get_table_goal(PredId, ProcId, VarTypes0, VarTypes1,
@@ -712,7 +718,10 @@
 	set__singleton_set(NonLocals0, TableVar),
 	set__insert_list(NonLocals0, Vars, NonLocals),
 	instmap_delta_from_assoc_list([], InstMapDelta),
-	init_goal_info(NonLocals, InstMapDelta, det, Context, GoalInfo),
+	init_goal_info(NonLocals, InstMapDelta, det, Context, GoalInfo0),
+	goal_info_get_features(GoalInfo0, Features0),
+	set__insert(Features0, call_table_gen, Features),
+	goal_info_set_features(GoalInfo0, Features, GoalInfo),
 	Goal = GoalEx - GoalInfo.
 
 :- pred generate_non_lookup_goal(list(prog_var)::in, pred_id::in, proc_id::in,
@@ -741,7 +750,10 @@
 	set__insert_list(NonLocals0, Vars, NonLocals),
 	create_instmap_delta(Goals, InstMapDelta0),
 	instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-	init_goal_info(NonLocals, InstMapDelta, det, Context, GoalInfo),
+	init_goal_info(NonLocals, InstMapDelta, det, Context, GoalInfo0),
+	goal_info_get_features(GoalInfo0, Features0),
+	set__insert(Features0, call_table_gen, Features),
+	goal_info_set_features(GoalInfo0, Features, GoalInfo),
 	Goal = GoalEx - GoalInfo.
 
 :- pred generate_lookup_goals(list(prog_var)::in, term__context::in,
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.36
diff -u -r1.36 trace.m
--- compiler/trace.m	2000/10/03 00:34:31	1.36
+++ compiler/trace.m	2000/10/05 12:04:13
@@ -73,29 +73,49 @@
 
 :- type trace_info.
 
-:- type trace_slot_info
-	--->	trace_slot_info(
-			maybe(int),	% If the procedure is shallow traced,
+:- type trace_slot_info --->
+	trace_slot_info(
+		slot_from_full		:: maybe(int),
+					% If the procedure is shallow traced,
 					% this will be yes(N), where stack
 					% slot N is the slot that holds the
 					% value of the from-full flag at call.
 					% Otherwise, it will be no.
 
-			maybe(int),	% If --trace-decl is set, this will
+		slot_decl		:: maybe(int),
+					% If --trace-decl is set, this will
 					% be yes(M), where stack slots M
 					% and M+1 are reserved for the runtime
 					% system to use in building proof
 					% trees for the declarative debugger.
 					% Otherwise, it will be no.
 
-			maybe(int)	% If --use-trail is set, this will
+		slot_trail		:: maybe(int),
+					% If --use-trail is set, this will
 					% be yes(M), where stack slots M
 					% and M+1 are the slots that hold the
 					% saved values of the trail pointer
 					% and the ticket counter respectively
 					% at the time of the call. Otherwise,
 					% it will be no.
-		).
+
+		slot_maxfr		:: maybe(int),
+					% If the procedure lives on the det
+					% stack but creates temporary frames
+					% on the nondet stack, this will be
+					% yes(M), where stack slot M is
+					% reserved to hold the value of maxfr
+					% at the time of the call. Otherwise,
+					% it will be no.
+
+		slot_call_table		:: maybe(int)
+					% If the procedure's evaluation method
+					% is memo, loopcheck or minimal model, 
+					% this will be yes(M), where stack slot
+					% M holds the variable that represents
+					% the tip of the call table. Otherwise,
+					% it will be no.
+	).
 
 	% Return the set of input variables whose values should be preserved
 	% until the exit and fail ports. This will be all the input variables,
@@ -103,20 +123,30 @@
 	% of the procedure (those partially clobbered may still be of interest,
 	% although to handle them properly we need to record insts in stack
 	% layouts).
-:- pred trace__fail_vars(module_info::in, proc_info::in, set(prog_var)::out)
-	is det.
+:- pred trace__fail_vars(module_info::in, proc_info::in,
+		set(prog_var)::out) is det.
+
+	% Figure out whether we need a slot for storing the value of maxfr
+	% on entry, and record the result in the proc info.
+:- pred trace__do_we_need_maxfr_slot(globals::in, proc_info::in,
+	proc_info::out) is det.
 
 	% Return the number of slots reserved for tracing information.
 	% If there are N slots, the reserved slots will be 1 through N.
-:- pred trace__reserved_slots(proc_info::in, globals::in, int::out) is det.
+	%
+	% It is possible that one of these reserved slots contains a variable.
+	% If so, the variable and its slot number are returned in the last
+	% argument.
+:- pred trace__reserved_slots(proc_info::in, globals::in, int::out,
+	maybe(pair(prog_var, int))::out) is det.
 
 	% Construct and return an abstract struct that represents the
 	% tracing-specific part of the code generator state. Return also
 	% info about the non-fixed slots used by the tracing system,
 	% for eventual use in the constructing the procedure's layout
 	% structure.
-:- pred trace__setup(globals::in, trace_slot_info::out, trace_info::out,
-	code_info::in, code_info::out) is det.
+:- pred trace__setup(proc_info::in, globals::in, trace_slot_info::out,
+	trace_info::out, code_info::in, code_info::out) is det.
 
 	% Generate code to fill in the reserved stack slots.
 :- pred trace__generate_slot_fill_code(trace_info::in, code_tree::out,
@@ -179,7 +209,7 @@
 :- implementation.
 
 :- import_module continuation_info, trace_params, type_util, llds_out, tree.
-:- import_module (inst), instmap, inst_match, mode_util, options.
+:- import_module (inst), instmap, inst_match, code_util, mode_util, options.
 :- import_module list, bool, int, string, map, std_util, require, term, varset.
 
 	% Information specific to a trace port.
@@ -211,9 +241,24 @@
 		error("length mismatch in trace__fail_vars")
 	).
 
+trace__do_we_need_maxfr_slot(Globals, ProcInfo0, ProcInfo) :-
+	globals__get_trace_level(Globals, TraceLevel),
+	proc_info_interface_code_model(ProcInfo0, CodeModel),
+	(
+		trace_level_is_none(TraceLevel) = no,
+		CodeModel \= model_non,
+		proc_info_goal(ProcInfo0, Goal),
+		code_util__goal_may_alloc_temp_frame(Goal)
+	->
+		MaxfrFlag = yes
+	;
+		MaxfrFlag = no
+	),
+	proc_info_set_need_maxfr_slot(ProcInfo0, MaxfrFlag, ProcInfo).
+
 	% trace__reserved_slots and trace__setup cooperate in the allocation
-	% of stack slots for tracing purposes. The allocation is done in five
-	% stages.
+	% of stack slots for tracing purposes. The allocation is done in the
+	% following stages.
 	%
 	% stage 1:	Allocate the fixed slots, slots 1, 2 and 3, to hold
 	%		the event number of call, the call sequence number
@@ -244,11 +289,22 @@
 	%		in the proc layout; if there are no such slots, that
 	%		field will contain -1.
 	%
-	% The runtime system cannot know whether the stack frame has a slot
-	% that holds the saved from-full flag and whether it has the slots
-	% for the proof tree. This is why trace__setup returns TraceSlotInfo,
-	% which answers these questions, for later inclusion in the
-	% procedure's layout structure.
+	% stage 6:	If the procedure lives on the det stack but can put
+	%		frames on the nondet stack, allocate a slot to hold
+	%		the saved value of maxfr at the point of the call,
+	%		for use in implementing retry. The number of this
+	%		slot is recorded in the maybe_maxfr field in the proc
+	%		layout; if there is no such slot, that field will
+	%		contain -1.
+	%
+	% stage 7:	If the procedure's evaluation method is memo, loopcheck
+	%		or minimal model, we allocate a slot to hold the
+	%		variable that represents the tip of the call table.
+	%		The debugger needs this, because when it executes a
+	%		retry command, it must reset this tip to uninitialized.
+	%		The number of this slot is recorded in the maybe_table
+	%		field in the proc layout; if there is no such slot,
+	%		that field will contain -1.
 	%
 	% The procedure's layout structure does not need to include
 	% information about the presence or absence of the slot holding
@@ -265,14 +321,23 @@
 	% their redos thus checks this slot to see whether it can (or should)
 	% access the other slots. In shallow-traced model_non procedures
 	% that generate redo events, the from-full flag is always in slot 5.
+	%
+	% The slots allocated by stages 1 and 2 are only ever referred to
+	% by the runtime system if they are guaranteed to exist. The runtime
+	% system may of course also need to refer to slots allocated by later
+	% stages, but before it does so, it needs to know whether those slots
+	% exist or not. This is why trace__setup returns TraceSlotInfo,
+	% which answers such questions, for later inclusion in the
+	% procedure's layout structure.
 
-trace__reserved_slots(ProcInfo, Globals, ReservedSlots) :-
+trace__reserved_slots(ProcInfo, Globals, ReservedSlots, MaybeTableVarInfo) :-
 	globals__get_trace_level(Globals, TraceLevel),
 	globals__get_trace_suppress(Globals, TraceSuppress),
 	FixedSlots = trace_level_needs_fixed_slots(TraceLevel),
 	(
 		FixedSlots = no,
-		ReservedSlots = 0
+		ReservedSlots = 0,
+		MaybeTableVarInfo = no
 	;
 		FixedSlots = yes,
 		Fixed = 3, % event#, call#, call depth
@@ -299,12 +364,28 @@
 			Trail = 2
 		;
 			Trail = 0
+		),
+		proc_info_get_need_maxfr_slot(ProcInfo, NeedMaxfr),
+		(
+			NeedMaxfr = yes,
+			Maxfr = 1
+		;
+			NeedMaxfr = no,
+			Maxfr = 0
 		),
-		ReservedSlots is Fixed + RedoLayout + FromFull + DeclDebug +
-			Trail
+		ReservedSlots0 = Fixed + RedoLayout + FromFull + DeclDebug +
+			Trail + Maxfr,
+		proc_info_get_call_table_tip(ProcInfo, MaybeCallTableVar),
+		( MaybeCallTableVar = yes(CallTableVar) ->
+			ReservedSlots = ReservedSlots0 + 1,
+			MaybeTableVarInfo = yes(CallTableVar - ReservedSlots)
+		;
+			ReservedSlots = ReservedSlots0,
+			MaybeTableVarInfo = no
+		)
 	).
 
-trace__setup(Globals, TraceSlotInfo, TraceInfo) -->
+trace__setup(ProcInfo, Globals, TraceSlotInfo, TraceInfo) -->
 	code_info__get_proc_model(CodeModel),
 	{ globals__get_trace_level(Globals, TraceLevel) },
 	{ globals__get_trace_suppress(Globals, TraceSuppress) },
@@ -314,10 +395,10 @@
 		{ CodeModel = model_non }
 	->
 		code_info__get_next_label(RedoLayoutLabel),
-		{ MaybeRedoLayout = yes(RedoLayoutLabel) },
+		{ MaybeRedoLayoutLabel = yes(RedoLayoutLabel) },
 		{ NextSlotAfterRedoLayout = 5 }
 	;
-		{ MaybeRedoLayout = no },
+		{ MaybeRedoLayoutLabel = no },
 		{ NextSlotAfterRedoLayout = 4 }
 	),
 	{ trace_level_needs_from_full_slot(TraceLevel) = FromFullSlot },
@@ -329,11 +410,8 @@
 	;
 		FromFullSlot = yes,
 		MaybeFromFullSlot = yes(NextSlotAfterRedoLayout),
-		( CodeModel = model_non ->
-			CallFromFullSlot = framevar(NextSlotAfterRedoLayout)
-		;
-			CallFromFullSlot = stackvar(NextSlotAfterRedoLayout)
-		),
+		CallFromFullSlot = llds__stack_slot_num_to_lval(
+			CodeModel, NextSlotAfterRedoLayout),
 		MaybeFromFullSlotLval = yes(CallFromFullSlot),
 		NextSlotAfterFromFull is NextSlotAfterRedoLayout + 1
 	},
@@ -349,29 +427,54 @@
 	},
 	{ globals__lookup_bool_option(Globals, use_trail, yes) ->
 		MaybeTrailSlot = yes(NextSlotAfterDecl),
-		( CodeModel = model_non ->
-			TrailLval =  framevar(NextSlotAfterDecl),
-			TicketLval = framevar(NextSlotAfterDecl+1)
-		;
-			TrailLval =  stackvar(NextSlotAfterDecl),
-			TicketLval = stackvar(NextSlotAfterDecl+1)
-		),
-		MaybeTrailLvals = yes(TrailLval - TicketLval)
+		TrailLval = llds__stack_slot_num_to_lval(CodeModel,
+			NextSlotAfterDecl),
+		TicketLval = llds__stack_slot_num_to_lval(CodeModel,
+			NextSlotAfterDecl + 1),
+		MaybeTrailLvals = yes(TrailLval - TicketLval),
+		NextSlotAfterTrail = NextSlotAfterDecl + 2
 	;
 		MaybeTrailSlot = no,
-		MaybeTrailLvals = no
+		MaybeTrailLvals = no,
+		NextSlotAfterTrail = NextSlotAfterDecl
+	},
+	{ proc_info_get_need_maxfr_slot(ProcInfo, NeedMaxfr) },
+	{
+		NeedMaxfr = yes,
+		MaybeMaxfrSlot = yes(NextSlotAfterTrail),
+		MaxfrLval = llds__stack_slot_num_to_lval(CodeModel,
+			NextSlotAfterTrail),
+		MaybeMaxfrLval = yes(MaxfrLval),
+		NextSlotAfterMaxfr = NextSlotAfterTrail + 1
+	;
+		NeedMaxfr = no,
+		MaybeMaxfrSlot = no,
+		MaybeMaxfrLval = no,
+		NextSlotAfterMaxfr = NextSlotAfterTrail
 	},
-	{ TraceSlotInfo = trace_slot_info(MaybeFromFullSlot,
-		MaybeDeclSlots, MaybeTrailSlot) },
+	{ proc_info_get_call_table_tip(ProcInfo, yes(_)) ->
+		MaybeCallTableSlot = yes(NextSlotAfterMaxfr),
+		CallTableLval = llds__stack_slot_num_to_lval(CodeModel,
+			NextSlotAfterMaxfr),
+		MaybeCallTableLval = yes(CallTableLval)
+	;
+		MaybeCallTableSlot = no,
+		MaybeCallTableLval = no
+	},
+	{ TraceSlotInfo = trace_slot_info(MaybeFromFullSlot, MaybeDeclSlots,
+		MaybeTrailSlot, MaybeMaxfrSlot, MaybeCallTableSlot) },
 	{ TraceInfo = trace_info(TraceLevel, TraceSuppress,
-		MaybeFromFullSlotLval, MaybeTrailLvals, MaybeRedoLayout) }.
+		MaybeFromFullSlotLval, MaybeTrailLvals, MaybeMaxfrLval,
+		MaybeCallTableLval, MaybeRedoLayoutLabel) }.
 
 trace__generate_slot_fill_code(TraceInfo, TraceCode) -->
 	code_info__get_proc_model(CodeModel),
 	{
-	MaybeFromFullSlot = TraceInfo ^ from_full_lval,
-	MaybeRedoLabel = TraceInfo ^ redo_label,
-	MaybeTrailLvals = TraceInfo ^ trail_lvals,
+	MaybeFromFullSlot  = TraceInfo ^ from_full_lval,
+	MaybeTrailLvals    = TraceInfo ^ trail_lvals,
+	MaybeMaxfrLval     = TraceInfo ^ maxfr_lval,
+	MaybeCallTableLval = TraceInfo ^ call_table_tip_lval,
+	MaybeRedoLabel     = TraceInfo ^ redo_label,
 	trace__event_num_slot(CodeModel, EventNumLval),
 	trace__call_num_slot(CodeModel, CallNumLval),
 	trace__call_depth_slot(CodeModel, CallDepthLval),
@@ -410,10 +513,25 @@
 			FillFourSlots, "\n",
 			"\t\tMR_mark_ticket_stack(", TicketLvalStr, ");\n",
 			"\t\tMR_store_ticket(", TrailLvalStr, ");"
-		], FillAllSlots)
+		], FillSixSlots)
 	;
 		MaybeTrailLvals = no,
-		FillAllSlots = FillFourSlots
+		FillSixSlots = FillFourSlots
+	),
+	(
+		% This could be done by generating proper LLDS instead of C.
+		% However, in shallow traced code we want to execute this
+		% only when the caller is deep traced, and everything inside
+		% that test must be in C code.
+		MaybeMaxfrLval = yes(MaxfrLval),
+		trace__stackref_to_string(MaxfrLval, MaxfrLvalStr),
+		string__append_list([
+			FillSixSlots,
+			"\n\t\t", MaxfrLvalStr, " = (Word) MR_maxfr;"
+		], FillCondSlots)
+	;
+		MaybeMaxfrLval = no,
+		FillCondSlots = FillSixSlots
 	),
 	(
 		MaybeFromFullSlot = yes(CallFromFullSlot),
@@ -422,20 +540,35 @@
 		string__append_list([
 			"\t\t", CallFromFullSlotStr, " = MR_trace_from_full;\n",
 			"\t\tif (MR_trace_from_full) {\n",
-			FillAllSlots, "\n",
+			FillCondSlots, "\n",
 			"\t\t} else {\n",
 			"\t\t\t", CallDepthStr, " = MR_trace_call_depth;\n",
 			"\t\t}"
-		], TraceStmt)
+		], TraceStmt1)
 	;
 		MaybeFromFullSlot = no,
-		TraceStmt = FillAllSlots
+		TraceStmt1 = FillCondSlots
 	),
-	TraceCode = node([
-		pragma_c([], [pragma_c_raw_code(TraceStmt)],
+	TraceCode1 = node([
+		pragma_c([], [pragma_c_raw_code(TraceStmt1)],
 			will_not_call_mercury, no, MaybeLayoutLabel, no, yes)
 			- ""
-	])
+	]),
+	(
+		MaybeCallTableLval = yes(CallTableLval),
+		trace__stackref_to_string(CallTableLval, CallTableLvalStr),
+		string__append_list([
+			"\t\t", CallTableLvalStr, " = 0;"
+		], TraceStmt2),
+		TraceCode2 = node([
+			pragma_c([], [pragma_c_raw_code(TraceStmt2)],
+				will_not_call_mercury, no, no, no, yes) - ""
+		])
+	;
+		MaybeCallTableLval = no,
+		TraceCode2 = empty
+	),
+	TraceCode = tree(TraceCode1, TraceCode2)
 	}.
 
 trace__prepare_for_call(TraceCode) -->
@@ -800,7 +933,8 @@
 trace__path_step_to_string(ite_then, "t;").
 trace__path_step_to_string(ite_else, "e;").
 trace__path_step_to_string(neg, "~;").
-trace__path_step_to_string(exist, "q;").
+trace__path_step_to_string(exist(cut), "q!;").
+trace__path_step_to_string(exist(no_cut), "q;").
 trace__path_step_to_string(first, "f;").
 trace__path_step_to_string(later, "l;").
 
@@ -871,6 +1005,15 @@
 					% of the slots that hold the value
 					% of the trail pointer and the ticket
 					% counter at the time of the call.
+		maxfr_lval		:: maybe(lval),	
+					% If we reserve a slot for holding
+					% the value of maxfr at entry for use
+					% in implementing retry, the lval of
+					% the slot.
+		call_table_tip_lval	:: maybe(lval),
+					% If we reserve a slot for holding
+					% the value of the call table tip
+					% variable, the lval of this variable.
 		redo_label		:: maybe(label)
 					% If we are generating redo events,
 					% this has the label associated with
Index: compiler/value_number.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/value_number.m,v
retrieving revision 1.105
diff -u -r1.105 value_number.m
--- compiler/value_number.m	2000/08/11 08:19:21	1.105
+++ compiler/value_number.m	2000/10/01 07:18:39
@@ -1118,7 +1118,7 @@
 	;
 		Boundary = no
 	).
-value_number__boundary_instr(call(_, _, _, _, _), yes).
+value_number__boundary_instr(call(_, _, _, _, _, _), yes).
 value_number__boundary_instr(mkframe(_, _), yes).
 value_number__boundary_instr(label(_), yes).
 value_number__boundary_instr(goto(_), yes).
Index: compiler/vn_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_block.m,v
retrieving revision 1.65
diff -u -r1.65 vn_block.m
--- compiler/vn_block.m	2000/08/11 08:19:23	1.65
+++ compiler/vn_block.m	2000/10/01 07:18:39
@@ -237,11 +237,11 @@
 		Specials = LeftSpecials
 	),
 	set__insert_list(Liveset0, Specials, Liveset).
-vn_block__handle_instr(call(Proc, Return, Info, Context, CallModel),
+vn_block__handle_instr(call(Proc, Return, Info, Context, GoalPath, CallModel),
 		Livemap, Params, VnTables0, VnTables, Liveset0, Liveset,
 		SeenIncr, SeenIncr, Tuple0, Tuple) :-
 	vn_block__new_ctrl_node(vn_call(Proc, Return, Info, Context,
-		CallModel), Livemap, Params, VnTables0, VnTables,
+		GoalPath, CallModel), Livemap, Params, VnTables0, VnTables,
 		Liveset0, Liveset, Tuple0, Tuple).
 vn_block__handle_instr(mkframe(NondetFrameInfo, Redoip), Livemap, Params,
 		VnTables0, VnTables, Liveset0, Liveset,
@@ -418,7 +418,7 @@
 		C = C0,
 		Parallels = []
 	;
-		VnInstr = vn_call(_, _, _, _, _),
+		VnInstr = vn_call(_, _, _, _, _, _),
 		vn_block__record_at_call(VnTables0, VnTables, Liveset0, Liveset,
 			FlushEntry0, FlushEntry),
 		C = C0,
@@ -924,7 +924,7 @@
 vn_block__is_ctrl_instr(livevals(_), yes).
 vn_block__is_ctrl_instr(block(_, _, _), no).
 vn_block__is_ctrl_instr(assign(_, _), no).
-vn_block__is_ctrl_instr(call(_, _, _, _, _), yes).
+vn_block__is_ctrl_instr(call(_, _, _, _, _, _), yes).
 vn_block__is_ctrl_instr(mkframe(_, _), yes).
 vn_block__is_ctrl_instr(label(_), yes).
 vn_block__is_ctrl_instr(goto(_), yes).
Index: compiler/vn_cost.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_cost.m,v
retrieving revision 1.43
diff -u -r1.43 vn_cost.m
--- compiler/vn_cost.m	2000/10/06 10:18:39	1.43
+++ compiler/vn_cost.m	2000/10/09 00:57:43
@@ -108,7 +108,7 @@
 			Cost is RvalCost + LvalCost + AssignCost
 		)
 	;
-		Uinstr = call(_, _, _, _, _),
+		Uinstr = call(_, _, _, _, _, _),
 		Cost = 0
 	;
 		Uinstr = mkframe(_, _),
Index: compiler/vn_filter.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_filter.m,v
retrieving revision 1.26
diff -u -r1.26 vn_filter.m
--- compiler/vn_filter.m	2000/04/26 05:40:44	1.26
+++ compiler/vn_filter.m	2000/10/01 07:18:39
@@ -135,7 +135,7 @@
 vn_filter__user_instr(block(_, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__user_instr(assign(_, Rval), yes(Rval)).
-vn_filter__user_instr(call(_, _, _, _, _), no).
+vn_filter__user_instr(call(_, _, _, _, _, _), no).
 vn_filter__user_instr(mkframe(_, _), no).
 vn_filter__user_instr(label(_), no).
 vn_filter__user_instr(goto(_), no).
@@ -183,7 +183,7 @@
 vn_filter__replace_in_user_instr(assign(Lval, Rval0), Temp, Defn,
 		assign(Lval, Rval)) :-
 	vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
-vn_filter__replace_in_user_instr(call(_, _, _, _, _), _, _, _) :-
+vn_filter__replace_in_user_instr(call(_, _, _, _, _, _), _, _, _) :-
 	error("non-user instruction in vn_filter__replace_in_user_instr").
 vn_filter__replace_in_user_instr(mkframe(_, _), _, _, _) :-
 	error("non-user instruction in vn_filter__replace_in_user_instr").
@@ -249,7 +249,7 @@
 vn_filter__defining_instr(block(_, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__defining_instr(assign(Lval, _), yes(Lval)).
-vn_filter__defining_instr(call(_, _, _, _, _), no).
+vn_filter__defining_instr(call(_, _, _, _, _, _), no).
 vn_filter__defining_instr(mkframe(_, _), no).
 vn_filter__defining_instr(label(_), no).
 vn_filter__defining_instr(goto(_), no).
@@ -297,7 +297,7 @@
 vn_filter__replace_in_defining_instr(assign(Lval0, Rval), Temp, Defn,
 		assign(Lval, Rval)) :-
 	vn_filter__replace_in_lval(Lval0, Temp, Defn, Lval).
-vn_filter__replace_in_defining_instr(call(_, _, _, _, _), _, _, _) :-
+vn_filter__replace_in_defining_instr(call(_, _, _, _, _, _), _, _, _) :-
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
 vn_filter__replace_in_defining_instr(mkframe(_, _), _, _, _) :-
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
Index: compiler/vn_flush.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_flush.m,v
retrieving revision 1.52
diff -u -r1.52 vn_flush.m
--- compiler/vn_flush.m	2000/03/20 05:26:42	1.52
+++ compiler/vn_flush.m	2000/10/01 07:18:39
@@ -186,11 +186,11 @@
 		Instrs = [livevals(Livevals) - ""]
 	;
 		Vn_instr = vn_call(ProcAddr, RetAddr, LiveInfo,
-			Context, CodeModel),
+			Context, GoalPath, CodeModel),
 		VnTables = VnTables0,
 		Templocs = Templocs0,
 		Instrs = [call(ProcAddr, RetAddr, LiveInfo,
-			Context, CodeModel) - ""]
+			Context, GoalPath, CodeModel) - ""]
 	;
 		Vn_instr = vn_mkframe(NondetFrameInfo, Redoip),
 		vn_util__rval_to_vn(const(code_addr_const(Redoip)), AddrVn,
Index: compiler/vn_order.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_order.m,v
retrieving revision 1.51
diff -u -r1.51 vn_order.m
--- compiler/vn_order.m	2000/03/20 05:26:44	1.51
+++ compiler/vn_order.m	2000/10/01 07:18:39
@@ -323,7 +323,7 @@
 			Predmap1 = Predmap0,
 			VnTables1 = VnTables0
 		;
-			Vn_instr = vn_call(_, _, _, _, _),
+			Vn_instr = vn_call(_, _, _, _, _, _),
 			Succmap1 = Succmap0,
 			Predmap1 = Predmap0,
 			VnTables1 = VnTables0
Index: compiler/vn_type.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_type.m,v
retrieving revision 1.45
diff -u -r1.45 vn_type.m
--- compiler/vn_type.m	2000/08/11 08:19:24	1.45
+++ compiler/vn_type.m	2000/10/01 07:18:39
@@ -13,7 +13,7 @@
 :- module vn_type.
 
 :- interface.
-:- import_module llds, builtin_ops, livemap, options.
+:- import_module hlds_goal, llds, builtin_ops, livemap, options.
 :- import_module getopt, map, set, list, std_util, counter.
 
 :- type vn == int.
@@ -71,7 +71,7 @@
 
 :- type vn_instr	--->	vn_livevals(lvalset)
 			;	vn_call(code_addr, code_addr, list(liveinfo),
-					term__context, call_model)
+					term__context, goal_path, call_model)
 			;	vn_mkframe(nondet_frame_info, code_addr)
 			;	vn_label(label)
 			;	vn_goto(code_addr)
Index: compiler/vn_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_util.m,v
retrieving revision 1.69
diff -u -r1.69 vn_util.m
--- compiler/vn_util.m	2000/03/20 05:26:46	1.69
+++ compiler/vn_util.m	2000/10/01 07:18:39
@@ -1228,7 +1228,7 @@
 			VnInstr = vn_livevals(_),
 			VnTables1 = VnTables0
 		;
-			VnInstr = vn_call(_, _, _, _, _),
+			VnInstr = vn_call(_, _, _, _, _, _),
 			VnTables1 = VnTables0
 		;
 			VnInstr = vn_mkframe(_, _),
Index: compiler/vn_verify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_verify.m,v
retrieving revision 1.26
diff -u -r1.26 vn_verify.m
--- compiler/vn_verify.m	2000/04/26 05:40:45	1.26
+++ compiler/vn_verify.m	2000/10/01 07:18:39
@@ -297,7 +297,7 @@
 		set__delete(NoDeref2, lval(Lval), NoDeref),
 		vn_verify__tags_rval(Rval, NoDeref)
 	;
-		Instr = call(_, _, _, _, _),
+		Instr = call(_, _, _, _, _, _),
 		NoDeref = NoDeref0,
 		Tested = Tested0
 	;
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.221
diff -u -r1.221 user_guide.texi
--- doc/user_guide.texi	2000/10/03 00:34:52	1.221
+++ doc/user_guide.texi	2000/10/04 05:39:24
@@ -1784,8 +1784,8 @@
 By default, this command is strict, and it uses the default print level.
 @sp 1
 @item finish [-NSans] [@var{num}]
-Continues execution until it reaches a final (EXIT, FAIL or EXCP) port of
-the @var{num}'th ancestor of the call to which the current event refers.
+Continues execution until it reaches a final (EXIT, FAIL or EXCP) port
+of the @var{num}'th ancestor of the call to which the current event refers.
 The default value of @var{num} is zero,
 which means skipping to the end of the current call.
 Reports an error if execution is already at the desired port.
@@ -1798,6 +1798,24 @@
 the strictness of the command.
 @sp 1
 By default, this command is strict, and it uses the default print level.
+ at c @sp 1
+ at c @item fail [-NSans] [@var{num}]
+ at c Continues execution until it reaches a FAIL or EXCP port
+ at c of the @var{num}'th ancestor of the call to which the current event refers.
+ at c The default value of @var{num} is zero,
+ at c which means skipping to the end of the current call.
+ at c Reports an error if execution is already at the desired port,
+ at c or if the determinism of the selected call
+ at c does not guarantee that it will eventually fail.
+ at c @sp 1
+ at c The options @samp{-n} or @samp{--none}, @samp{-s} or @samp{--some},
+ at c @samp{-a} or @samp{--all} specify the print level to use
+ at c for the duration of the command,
+ at c while the options @samp{-S} or @samp{--strict}
+ at c and @samp{-N} or @samp{--nostrict} specify
+ at c the strictness of the command.
+ at c @sp 1
+ at c By default, this command is strict, and it uses the default print level.
 @sp 1
 @item exception [-NSans]
 Continues the program until execution reaches an exception event.
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing library
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/mercury_regorder.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_regorder.h,v
retrieving revision 1.14
diff -u -r1.14 mercury_regorder.h
--- runtime/mercury_regorder.h	2000/08/03 06:18:52	1.14
+++ runtime/mercury_regorder.h	2000/10/05 02:08:02
@@ -152,6 +152,11 @@
 #define MR_saved_cut_stack(save_area)	LVALUE_CAST(			      \
 					struct MR_CutStackFrameStruct *,      \
 					save_area[45])
+#define MR_saved_r1(save_area)		LVALUE_CAST(MR_Word, save_area[3])
+#define MR_saved_r2(save_area)		LVALUE_CAST(MR_Word, save_area[4])
+#define MR_saved_r3(save_area)		LVALUE_CAST(MR_Word, save_area[5])
+#define MR_saved_r4(save_area)		LVALUE_CAST(MR_Word, save_area[7])
+#define MR_saved_r5(save_area)		LVALUE_CAST(MR_Word, save_area[8])
 
 #define VIRTUAL_REG_MAP_BODY	{ \
 	3, \
@@ -308,6 +313,11 @@
 #define MR_saved_cut_next(save_area)	LVALUE_CAST(			      \
 					struct MR_CutStackFrameStruct *,      \
 					save_area[44])
+#define MR_saved_r1(save_area)		LVALUE_CAST(MR_Word, save_area[2])
+#define MR_saved_r2(save_area)		LVALUE_CAST(MR_Word, save_area[3])
+#define MR_saved_r3(save_area)		LVALUE_CAST(MR_Word, save_area[4])
+#define MR_saved_r4(save_area)		LVALUE_CAST(MR_Word, save_area[6])
+#define MR_saved_r5(save_area)		LVALUE_CAST(MR_Word, save_area[7])
 
 #define VIRTUAL_REG_MAP_BODY	{ \
 	2, \
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.39
diff -u -r1.39 mercury_stack_layout.h
--- runtime/mercury_stack_layout.h	2000/10/01 03:13:41	1.39
+++ runtime/mercury_stack_layout.h	2000/10/04 13:49:57
@@ -338,6 +338,13 @@
 	MR_Stack_Layout_Compiler_Proc	MR_proc_comp;
 } MR_Stack_Layout_Proc_Id;
 
+typedef	enum {
+	MR_EVAL_METHOD_NORMAL,
+	MR_EVAL_METHOD_LOOP_CHECK,
+	MR_EVAL_METHOD_MEMO,
+	MR_EVAL_METHOD_MINIMAL
+} MR_EvalMethod;
+
 typedef	struct MR_Stack_Layout_Entry_Struct {
 	/* stack traversal group */
 	MR_Code			*MR_sle_code_addr;
@@ -359,6 +366,9 @@
 	MR_int_least16_t	MR_sle_max_r_num;
 	MR_int_least8_t		MR_sle_maybe_from_full;
 	MR_int_least8_t		MR_sle_maybe_trail;
+	MR_int_least8_t		MR_sle_maybe_maxfr;
+	MR_EvalMethod		MR_sle_eval_method:8;
+	MR_int_least8_t		MR_sle_maybe_call_table;
 	MR_int_least8_t		MR_sle_maybe_decl_debug;
 } MR_Stack_Layout_Entry;
 
@@ -490,6 +500,10 @@
 	MR_int_least16_t	MR_sll_goal_path;
 	MR_Stack_Layout_Vars	MR_sll_var_info;
 } MR_Stack_Layout_Label;
+
+#define	MR_label_goal_path(layout)					\
+	((layout)->MR_sll_entry->MR_sle_module_layout->MR_ml_string_table\
+	+ (layout)->MR_sll_goal_path)
 
 /*
 ** Define a stack layout for an internal label.
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.36
diff -u -r1.36 mercury_stack_trace.c
--- runtime/mercury_stack_trace.c	2000/09/01 00:50:22	1.36
+++ runtime/mercury_stack_trace.c	2000/10/10 03:21:27
@@ -15,9 +15,10 @@
 #include "mercury_debug.h"
 #include <stdio.h>
 
-static	void	MR_dump_stack_record_init(bool include_contexts);
+static	void	MR_dump_stack_record_init(bool include_trace_data,
+			bool include_contexts);
 static	void	MR_dump_stack_record_frame(FILE *fp,
-			const MR_Stack_Layout_Label *,
+			const MR_Stack_Layout_Label *label_layout,
 			MR_Word *base_sp, MR_Word *base_curfr, 
 			MR_Print_Stack_Record print_stack_record);
 static	void	MR_dump_stack_record_flush(FILE *fp, 
@@ -68,8 +69,9 @@
 
 const char *
 MR_dump_stack_from_layout(FILE *fp, const MR_Stack_Layout_Label *label_layout,
-	MR_Word *det_stack_pointer, MR_Word *current_frame, bool include_trace_data,
-	bool include_contexts, MR_Print_Stack_Record print_stack_record)
+	MR_Word *det_stack_pointer, MR_Word *current_frame,
+	bool include_trace_data, bool include_contexts,
+	MR_Print_Stack_Record print_stack_record)
 {
 	MR_Stack_Walk_Step_Result	result;
 	const MR_Stack_Layout_Entry	*entry_layout;
@@ -82,7 +84,7 @@
 	MR_Word				*old_trace_curfr;
 
 	do_init_modules();
-	MR_dump_stack_record_init(include_contexts);
+	MR_dump_stack_record_init(include_trace_data, include_contexts);
 
 	stack_trace_sp = det_stack_pointer;
 	stack_trace_curfr = current_frame;
@@ -102,30 +104,16 @@
 			MR_dump_stack_record_flush(fp, print_stack_record);
 			return problem;
 		} else if (result == STEP_ERROR_AFTER) {
-			if (include_trace_data) {
-				MR_dump_stack_record_frame(fp,
-					prev_label_layout,
-					old_trace_sp, old_trace_curfr, 
-					print_stack_record);
-			} else {
-				MR_dump_stack_record_frame(fp,
-					prev_label_layout,
-					NULL, NULL, print_stack_record);
-			}
+			MR_dump_stack_record_frame(fp, prev_label_layout,
+				old_trace_sp, old_trace_curfr, 
+				print_stack_record);
 
 			MR_dump_stack_record_flush(fp, print_stack_record);
 			return problem;
 		} else {
-			if (include_trace_data) {
-				MR_dump_stack_record_frame(fp,
-					prev_label_layout,
-					old_trace_sp, old_trace_curfr, 
-					print_stack_record);
-			} else {
-				MR_dump_stack_record_frame(fp,
-					prev_label_layout,
-					NULL, NULL, print_stack_record);
-			}
+			MR_dump_stack_record_frame(fp, prev_label_layout,
+				old_trace_sp, old_trace_curfr, 
+				print_stack_record);
 		}
 	} while (cur_label_layout != NULL);
 
@@ -296,18 +284,21 @@
 static	MR_Word				*prev_entry_base_curfr;
 static	const char			*prev_entry_filename;
 static	int				prev_entry_linenumber;
+static	const char			*prev_entry_goal_path;
 static	bool				prev_entry_context_mismatch;
 static	int				current_level;
+static	bool				trace_data_enabled;
 static	bool				contexts_enabled;
 
 static void
-MR_dump_stack_record_init(bool include_contexts)
+MR_dump_stack_record_init(bool include_trace_data, bool include_contexts)
 {
 	prev_entry_layout = NULL;
 	prev_entry_layout_count = 0;
 	prev_entry_start_level = 0;
 	current_level = 0;
 	contexts_enabled = include_contexts;
+	trace_data_enabled = include_trace_data;
 }
 
 static void
@@ -337,17 +328,16 @@
 		(entry_layout != prev_entry_layout) ||
 
 		/*
-		** We cannot merge two calls even to the same procedure.
+		** We cannot merge two calls even to the same procedure
 		** if we are printing trace data, since this will differ
 		** between the calls.
 		**
 		** Note that it is not possible for two calls to the same
 		** procedure to differ on whether the procedure has trace
-		** layout data or not; this is why we don't have to test
-		** prev_entry_base_sp and prev_entry_base_curfr.
+		** layout data or not.
 		*/
 
-		((base_sp != NULL) || (base_curfr != NULL));
+		trace_data_enabled;
 
 	if (must_flush) {
 		MR_dump_stack_record_flush(fp, print_stack_record);
@@ -359,6 +349,7 @@
 		prev_entry_base_curfr = base_curfr;
 		prev_entry_filename = filename;
 		prev_entry_linenumber = linenumber;
+		prev_entry_goal_path = MR_label_goal_path(label_layout);
 		prev_entry_context_mismatch = FALSE;
 	} else {
 		prev_entry_layout_count++;
@@ -380,20 +371,21 @@
 			prev_entry_layout_count, prev_entry_start_level,
 			prev_entry_base_sp, prev_entry_base_curfr,
 			prev_entry_filename, prev_entry_linenumber,
-			prev_entry_context_mismatch);
+			prev_entry_goal_path, prev_entry_context_mismatch);
 	}
 }
 
 void
 MR_dump_stack_record_print(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
 	int count, int start_level, MR_Word *base_sp, MR_Word *base_curfr,
-	const char *filename, int linenumber, bool context_mismatch)
+	const char *filename, int linenumber, const char *goal_path,
+	bool context_mismatch)
 {
 	fprintf(fp, "%4d ", start_level);
 
 	if (count > 1) {
 		fprintf(fp, " %3d* ", count);
-	} else if ((base_sp == NULL) && (base_curfr == NULL)) {
+	} else if (! trace_data_enabled) {
 		fprintf(fp, "%5s ", "");
 	} else {
 		/*
@@ -403,13 +395,22 @@
 		*/
 	}
 
-	MR_print_call_trace_info(fp, entry_layout, base_sp, base_curfr);
+	MR_maybe_print_call_trace_info(fp, trace_data_enabled, entry_layout,
+		base_sp, base_curfr);
 	MR_print_proc_id(fp, entry_layout);
 	if (strdiff(filename, "") && linenumber > 0) {
 		fprintf(fp, " (%s:%d%s)", filename, linenumber,
 			context_mismatch ? " and others" : "");
 	}
 
+	if (trace_data_enabled) {
+		if (strdiff(goal_path, "")) {
+			fprintf(fp, " %s", goal_path);
+		} else {
+			fprintf(fp, " (empty)");
+		}
+	}
+
 	fprintf(fp, "\n");
 }
 
@@ -443,62 +444,79 @@
 }
 
 void
+MR_maybe_print_call_trace_info(FILE *fp, bool include_trace_data,
+	const MR_Stack_Layout_Entry *entry,
+	MR_Word *base_sp, MR_Word *base_curfr)
+{
+	if (include_trace_data) {
+		MR_print_call_trace_info(fp, entry, base_sp, base_curfr);
+	}
+}
+
+/*
+** Note that MR_print_call_trace_info is more permissive than its documentation
+** in the header file.
+*/
+
+void
 MR_print_call_trace_info(FILE *fp, const MR_Stack_Layout_Entry *entry,
 	MR_Word *base_sp, MR_Word *base_curfr)
 {
 	bool	print_details;
 
-	if (base_sp != NULL && base_curfr != NULL) {
-		if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
-			MR_Integer maybe_from_full =
-				entry->MR_sle_maybe_from_full;
-			if (maybe_from_full > 0) {
-				/*
-				** For procedures compiled with shallow
-				** tracing, the details will be valid only
-				** if the value of MR_from_full saved in
-				** the appropriate stack slot was TRUE.
-			    	*/
-				if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
-					print_details = MR_based_stackvar(
-						base_sp, maybe_from_full);
-				} else {
-					print_details = MR_based_framevar(
-						base_curfr, maybe_from_full);
-				}
+	if (base_sp == NULL || base_curfr == NULL) {
+		return;
+	}
+
+	if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
+		MR_Integer maybe_from_full =
+			entry->MR_sle_maybe_from_full;
+		if (maybe_from_full > 0) {
+			/*
+			** For procedures compiled with shallow
+			** tracing, the details will be valid only
+			** if the value of MR_from_full saved in
+			** the appropriate stack slot was TRUE.
+			*/
+			if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+				print_details = MR_based_stackvar(
+					base_sp, maybe_from_full);
 			} else {
-				/*
-				** For procedures compiled with full tracing,
-				** we can always print out the details.
-				*/
-				print_details = TRUE;
+				print_details = MR_based_framevar(
+					base_curfr, maybe_from_full);
 			}
 		} else {
-			print_details = FALSE;
+			/*
+			** For procedures compiled with full tracing,
+			** we can always print out the details.
+			*/
+			print_details = TRUE;
 		}
+	} else {
+		print_details = FALSE;
+	}
 
-		if (print_details) {
-			if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
-				fprintf(fp, "%7lu %7lu %4lu ",
-					(unsigned long)
-					MR_event_num_stackvar(base_sp) + 1,
-					(unsigned long)
-					MR_call_num_stackvar(base_sp),
-					(unsigned long)
-					MR_call_depth_stackvar(base_sp));
-			} else {
-				fprintf(fp, "%7lu %7lu %4lu ",
-					(unsigned long)
-					MR_event_num_framevar(base_curfr) + 1,
-					(unsigned long)
-					MR_call_num_framevar(base_curfr),
-					(unsigned long)
-					MR_call_depth_framevar(base_curfr));
-			}
+	if (print_details) {
+		if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+			fprintf(fp, "%7lu %7lu %4lu ",
+				(unsigned long)
+				MR_event_num_stackvar(base_sp) + 1,
+				(unsigned long)
+				MR_call_num_stackvar(base_sp),
+				(unsigned long)
+				MR_call_depth_stackvar(base_sp));
 		} else {
-			/* ensure that the remaining columns line up */
-			fprintf(fp, "%21s", "");
+			fprintf(fp, "%7lu %7lu %4lu ",
+				(unsigned long)
+				MR_event_num_framevar(base_curfr) + 1,
+				(unsigned long)
+				MR_call_num_framevar(base_curfr),
+				(unsigned long)
+				MR_call_depth_framevar(base_curfr));
 		}
+	} else {
+		/* ensure that the remaining columns line up */
+		fprintf(fp, "%21s", "");
 	}
 }
 
@@ -578,8 +596,9 @@
 }
 
 void
-MR_print_proc_id_trace_and_context(FILE *fp, MR_Context_Position pos,
-	const MR_Stack_Layout_Entry *entry, MR_Word *base_sp, MR_Word *base_curfr,
+MR_print_proc_id_trace_and_context(FILE *fp, bool include_trace_data,
+	MR_Context_Position pos, const MR_Stack_Layout_Entry *entry,
+	MR_Word *base_sp, MR_Word *base_curfr,
 	const char *path, const char *filename, int lineno, bool print_parent, 
 	const char *parent_filename, int parent_lineno, int indent)
 {
@@ -587,8 +606,8 @@
 	switch (pos) {
 		case MR_CONTEXT_NOWHERE:
 			fprintf(fp, " ");
-			MR_print_call_trace_info(fp, entry,
-				base_sp, base_curfr);
+			MR_maybe_print_call_trace_info(fp, include_trace_data,
+				entry, base_sp, base_curfr);
 			MR_print_proc_id(fp, entry);
 			if (strlen(path) > 0) {
 				fprintf(fp, " %s", path);
@@ -601,8 +620,8 @@
 			MR_maybe_print_parent_context(fp, print_parent,
 				FALSE, parent_filename, parent_lineno);
 			fprintf(fp, " ");
-			MR_print_call_trace_info(fp, entry,
-				base_sp, base_curfr);
+			MR_maybe_print_call_trace_info(fp, include_trace_data,
+				entry, base_sp, base_curfr);
 			MR_print_proc_id(fp, entry);
 			if (strlen(path) > 0) {
 				fprintf(fp, " %s", path);
@@ -612,8 +631,8 @@
 
 		case MR_CONTEXT_AFTER:
 			fprintf(fp, " ");
-			MR_print_call_trace_info(fp, entry,
-				base_sp, base_curfr);
+			MR_maybe_print_call_trace_info(fp, include_trace_data,
+				entry, base_sp, base_curfr);
 			MR_print_proc_id(fp, entry);
 			if (strlen(path) > 0) {
 				fprintf(fp, " %s", path);
@@ -629,8 +648,8 @@
 			MR_maybe_print_parent_context(fp, print_parent,
 				TRUE, parent_filename, parent_lineno);
 			fprintf(fp, "\n%*s ", indent, "");
-			MR_print_call_trace_info(fp, entry,
-				base_sp, base_curfr);
+			MR_maybe_print_call_trace_info(fp, include_trace_data,
+				entry, base_sp, base_curfr);
 			MR_print_proc_id(fp, entry);
 			if (strlen(path) > 0) {
 				fprintf(fp, " %s", path);
@@ -640,8 +659,8 @@
 
 		case MR_CONTEXT_NEXTLINE:
 			fprintf(fp, " ");
-			MR_print_call_trace_info(fp, entry,
-				base_sp, base_curfr);
+			MR_maybe_print_call_trace_info(fp, include_trace_data,
+				entry, base_sp, base_curfr);
 			MR_print_proc_id(fp, entry);
 			if (strlen(path) > 0) {
 				fprintf(fp, " %s", path);
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.22
diff -u -r1.22 mercury_stack_trace.h
--- runtime/mercury_stack_trace.h	2000/09/01 00:50:23	1.22
+++ runtime/mercury_stack_trace.h	2000/10/09 11:41:43
@@ -61,7 +61,7 @@
 				int count, int level,
 				MR_Word *base_sp, MR_Word * base_curfr,
 				const char *filename, int linenumber,
-				bool context_mismatch);
+				const char *goal_path, bool context_mismatch);
 
 extern	const char	*MR_dump_stack_from_layout(FILE *fp,
 				const MR_Stack_Layout_Label *label_layout,
@@ -165,16 +165,26 @@
 			const char **fileptr, int *lineptr);
 
 /*
-** If the procedure has trace layout information and the relevant one of
-** base_sp and base_curfr is not NULL, MR_print_call_trace_info prints
-** the call event number, call sequence number and call depth of the call
-** stored in the stack frame of the procedure.
+** MR_print_call_trace_info prints the call event number, call sequence number
+** and call depth of the call stored in the stack frame of the procedure
+** identified by the given proc layout. It requires the procedure to have
+** trace layout information, and the relevant one of base_sp and base_curfr
+** to be non-NULL, since these numbers are stored in stack slots.
+**
+** MR_maybe_print_call_trace_info calls MR_print_call_trace_info if
+** include_trace_data is TRUE and the other conditions required by
+** MR_print_call_trace_info are satisfied.
 */
 
 extern	void	MR_print_call_trace_info(FILE *fp,
 			const MR_Stack_Layout_Entry *entry,
 			MR_Word *base_sp, MR_Word *base_curfr);
 
+extern	void	MR_maybe_print_call_trace_info(FILE *fp,
+			bool include_trace_data,
+			const MR_Stack_Layout_Entry *entry,
+			MR_Word *base_sp, MR_Word *base_curfr);
+
 /*
 ** MR_print_proc_id prints an identification of the given procedure,
 ** consisting of "pred" or "func", module name, pred or func name, arity,
@@ -208,7 +218,7 @@
 } MR_Context_Position;
 
 extern	void	MR_print_proc_id_trace_and_context(FILE *fp,
-			MR_Context_Position pos,
+			bool include_trace_data, MR_Context_Position pos,
 			const MR_Stack_Layout_Entry *entry,
 			MR_Word *base_sp, MR_Word *base_curfr, const char *path,
 			const char *filename, int lineno, bool print_parent,
@@ -223,6 +233,6 @@
 			const MR_Stack_Layout_Entry *entry_layout, int count,
 			int start_level, MR_Word *base_sp, MR_Word *base_curfr,
 			const char *filename, int linenumber,
-			bool context_mismatch);
+			const char *goal_path, bool context_mismatch);
 
 #endif /* MERCURY_STACK_TRACE_H */
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/Mmakefile,v
retrieving revision 1.43
diff -u -r1.43 Mmakefile
--- tests/debugger/Mmakefile	2000/07/22 11:35:18	1.43
+++ tests/debugger/Mmakefile	2000/10/10 00:08:12
@@ -34,6 +34,7 @@
 	polymorphic_output		\
 	queens				\
 	resume_typeinfos		\
+	retry				\
 	shallow
 
 # The following tests are disabled, since currently they get some spurious
@@ -162,6 +163,9 @@
 	$(MDB) ./resume_typeinfos < resume_typeinfos.inp 2>&1 | \
 		sed 's/resume_typeinfos.m:[0-9]*/resume_typeinfos.m:NNNN/g' \
 		> resume_typeinfos.out 2>&1
+
+retry.out: retry retry.inp
+	$(MDB) ./retry < retry.inp > retry.out 2>&1
 
 shallow.out: shallow shallow.inp
 	$(MDB) ./shallow < shallow.inp > shallow.out 2>&1
Index: tests/debugger/exception_cmd.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/exception_cmd.exp,v
retrieving revision 1.1
diff -u -r1.1 exception_cmd.exp
--- tests/debugger/exception_cmd.exp	2000/07/22 08:20:07	1.1
+++ tests/debugger/exception_cmd.exp	2000/10/09 09:08:43
@@ -2,7 +2,7 @@
 mdb> echo on
 Command echo enabled.
 mdb> exception
-       4:      2  2 EXCP pred exception_cmd:test/2-0 (det) exception_cmd.m:18 (exception_cmd.m:12)
+       4:      2  2 EXCP pred exception_cmd:test/2-0 (det) t;c2; exception_cmd.m:18 (exception_cmd.m:12)
 mdb> print *
        HeadVar__1             	42
 mdb> continue
Index: tests/debugger/exception_value.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/exception_value.exp,v
retrieving revision 1.1
diff -u -r1.1 exception_value.exp
--- tests/debugger/exception_value.exp	2000/06/19 07:59:19	1.1
+++ tests/debugger/exception_value.exp	2000/10/09 09:09:01
@@ -9,7 +9,7 @@
 mdb> continue
        3:      3  3 CALL pred exception_value:p/1-0 (det) exception_value.m:30
 mdb> finish
-       4:      3  3 EXCP pred exception_value:p/1-0 (det) exception_value.m:31
+       4:      3  3 EXCP pred exception_value:p/1-0 (det) c3; exception_value.m:31
 mdb> print exception
 	"p exception"
 mdb> continue
@@ -19,7 +19,7 @@
 exception(univ("p exception" : string))
        7:      5  3 CALL pred exception_value:q/1-0 (det) exception_value.m:35
 mdb> finish
-       8:      5  3 EXCP pred exception_value:q/1-0 (det) exception_value.m:36
+       8:      5  3 EXCP pred exception_value:q/1-0 (det) c16; exception_value.m:36
 mdb> browse exception
 browser> set depth 9
 browser> set size 99
Index: tests/debugger/exception_vars.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/exception_vars.exp,v
retrieving revision 1.4
diff -u -r1.4 exception_vars.exp
--- tests/debugger/exception_vars.exp	2000/07/22 08:20:08	1.4
+++ tests/debugger/exception_vars.exp	2000/10/09 09:09:11
@@ -4,7 +4,7 @@
 mdb> goto 2
        2:      2  2 CALL pred exception_vars:test/2-0 (det) exception_vars.m:19 (exception_vars.m:12)
 mdb> finish
-       4:      2  2 EXCP pred exception_vars:test/2-0 (det) exception_vars.m:18 (exception_vars.m:12)
+       4:      2  2 EXCP pred exception_vars:test/2-0 (det) t;c2; exception_vars.m:18 (exception_vars.m:12)
 mdb> print *
        HeadVar__1             	42
 mdb> continue
Index: tests/debugger/loopcheck.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/loopcheck.exp,v
retrieving revision 1.2
diff -u -r1.2 loopcheck.exp
--- tests/debugger/loopcheck.exp	2000/03/22 04:08:10	1.2
+++ tests/debugger/loopcheck.exp	2000/10/09 09:09:38
@@ -16,11 +16,11 @@
                          loopcheck.m:21
        7:      3  3 THEN pred loopcheck:loop/1-0 (erroneous) c3;e;t;
                          loopcheck.m:21
-       8:      3  3 EXCP pred loopcheck:loop/1-0 (erroneous)
+       8:      3  3 EXCP pred loopcheck:loop/1-0 (erroneous) c3;e;t;c2;
                          loopcheck.m:21 (from loopcheck.m:21)
-       9:      2  2 EXCP pred loopcheck:loop/1-0 (erroneous)
+       9:      2  2 EXCP pred loopcheck:loop/1-0 (erroneous) c3;e;e;c2;
                          loopcheck.m:21 (from loopcheck.m:14)
-      10:      1  1 EXCP pred loopcheck:main/2-0 (det)
+      10:      1  1 EXCP pred loopcheck:main/2-0 (det) c2;
                          loopcheck.m:14
 Uncaught exception:
 Software Error: detected infinite recursion in pred loopcheck:loop/1
Index: tests/debugger/queens.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/queens.exp,v
retrieving revision 1.17
diff -u -r1.17 queens.exp
--- tests/debugger/queens.exp	1999/11/20 01:03:26	1.17
+++ tests/debugger/queens.exp	2000/10/09 11:56:32
@@ -122,20 +122,18 @@
    4       pred queens:queen/2-0 (nondet) (queens.m:42)
    5       pred queens:main/2-0 (cc_multi) (queens.m:15)
 mdb> stack -d
-   0      20      10    6 pred queens:qperm/2-0 (nondet) (queens.m:45)
-   1      15       8    5 pred queens:qperm/2-0 (nondet) (queens.m:49)
-   2      10       6    4 pred queens:qperm/2-0 (nondet) (queens.m:49)
-   3       5       4    3 pred queens:qperm/2-0 (nondet) (queens.m:49)
-   4       4       3    2 pred queens:queen/2-0 (nondet) (queens.m:42)
-   5       1       1    1 pred queens:main/2-0 (cc_multi) (queens.m:15)
+   0      20      10    6 pred queens:qperm/2-0 (nondet) (queens.m:45) (empty)
+   1      15       8    5 pred queens:qperm/2-0 (nondet) (queens.m:49) s1;c2;
+   2      10       6    4 pred queens:qperm/2-0 (nondet) (queens.m:49) s1;c2;
+   3       5       4    3 pred queens:qperm/2-0 (nondet) (queens.m:49) s1;c2;
+   4       4       3    2 pred queens:queen/2-0 (nondet) (queens.m:42) c2;
+   5       1       1    1 pred queens:main/2-0 (cc_multi) (queens.m:15) ?;c2;q!;
 mdb> print *
        HeadVar__1             	[4, 5]
 mdb> 
       21:     10  6 SWTC queens.m:46
                          pred queens:qperm/2-0 (nondet) s1;
 mdb> retry
-      34:     10  6 EXIT queens.m:45 (from queens.m:49)
-                         pred queens:qperm/2-0 (nondet)
       20:     10  6 CALL queens.m:45 (from queens.m:49)
                          pred queens:qperm/2-0 (nondet)
 mdb> print *
@@ -231,8 +229,6 @@
 mdb> disable 1
  1: - stop  interface pred queens:qdelete/3-0 (nondet)
 mdb> retry 4
-      76:      4  3 EXIT queens.m:45 (from queens.m:42)
-                         pred queens:qperm/2-0 (nondet)
        5:      4  3 CALL queens.m:45 (from queens.m:42)
                          pred queens:qperm/2-0 (nondet)
 mdb> break 49
Index: tests/debugger/retry.exp
===================================================================
RCS file: retry.exp
diff -N retry.exp
--- /dev/null	Thu Sep  2 15:00:04 1999
+++ retry.exp	Sun Oct  1 18:25:04 2000
@@ -0,0 +1,6 @@
+6
+4
+9
+40 41 
+50 51 
+987
Index: tests/debugger/retry.inp
===================================================================
RCS file: retry.inp
diff -N retry.inp
--- /dev/null	Thu Sep  2 15:00:04 1999
+++ retry.inp	Tue Oct 10 14:21:44 2000
@@ -0,0 +1,52 @@
+echo on
+register --quiet
+scroll off
+context none
+break det_without_cut_1
+continue -a
+disable 0
+retry
+stack
+finish
+retry 1
+stack
+break det_without_cut_2
+continue -a
+delete *
+retry 2
+finish
+stack
+break det_with_cut_1
+continue -a
+delete *
+finish
+retry 1
+finish
+stack
+retry 1
+break det_with_cut_2
+continue -a
+delete *
+break nondet
+continue
+print *
+break nondet_2
+continue
+retry 1
+print *
+delete *
+break fib
+continue
+print *
+all_regs
+continue
+print *
+continue
+continue
+step
+retry 2
+print *
+next
+all_regs
+retry 1
+continue -S
Index: tests/debugger/retry.m
===================================================================
RCS file: retry.m
diff -N retry.m
--- /dev/null	Thu Sep  2 15:00:04 1999
+++ retry.m	Tue Oct 10 14:23:12 2000
@@ -0,0 +1,143 @@
+% This test case tests the handling of the direct retries in mdb in the
+% situations that are most likely to cause problems. These are:
+%
+% - retry from within a committed-choice context
+% - retry from a model_non context
+% - retry that requires resetting the call table tips of some tabled
+%   procedures.
+%
+% Note: Don't try to print the call stack from within solutions in the input
+% script, since the results will depend on std_util.m was compiled with
+% debugging or not.
+
+:- module retry.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module std_util, list, int.
+
+main -->
+	{
+		det_without_cut(1, A),
+		det_with_cut(2, B),
+		det_with_cut(3, C),
+		solutions(nondet(4), Ds),
+		solutions(nondet(5), Es)
+	},
+	output(A),
+	output(B),
+	output(C),
+	outputs(Ds),
+	outputs(Es),
+	{ fib(15, F) },
+	output(F).
+
+%---------------------------------------------------------------------------%
+
+:- pred det_without_cut(int::in, int::out) is det.
+
+det_without_cut(X0, X) :-
+	det_without_cut_1(X0 + 2, X).
+
+:- pred det_without_cut_1(int::in, int::out) is det.
+
+det_without_cut_1(X0, X1 * 2) :-
+	det_without_cut_2(X0, X1).
+
+:- pred det_without_cut_2(int::in, int::out) is det.
+
+det_without_cut_2(X, X).
+
+%---------------------------------------------------------------------------%
+
+:- pred det_with_cut(int::in, int::out) is det.
+
+det_with_cut(X0, X) :-
+	( det_with_cut_1(X0, _) ->
+		X = X0 * 2
+	;
+		X = X0 * 3
+	).
+
+:- pred det_with_cut_1(int::in, int::out) is nondet.
+
+det_with_cut_1(X0, X) :-
+	X0 = 2,
+	(
+		det_with_cut_2(15, X)
+	;
+		X = 10
+	).
+
+:- pred det_with_cut_2(int::in, int::out) is det.
+
+det_with_cut_2(X, X).
+
+%---------------------------------------------------------------------------%
+
+:- pred nondet(int::in, int::out) is multi.
+
+nondet(X0, X) :-
+	nondet_1(X0, X1),
+	nondet_2(X1, X2),
+	( X2 < 75 ->
+		X = X2
+	;
+		X = 2 * X2
+	).
+
+:- pred nondet_1(int::in, int::out) is multi.
+
+nondet_1(X0, X) :-
+	X1 = 10 * X0,
+	(
+		X = X1
+	;
+		X = X1 + 1
+	).
+
+:- pred nondet_2(int::in, int::out) is det.
+
+nondet_2(X, X).
+
+%---------------------------------------------------------------------------%
+
+:- pred fib(int::in, int::out) is det.
+:- pragma memo(fib/2).
+
+fib(N, F) :-
+	( N < 2 ->
+		F = 1
+	;
+		fib(N - 1, F1),
+		fib(N - 2, F2),
+		F is F1 + F2
+	).
+
+%---------------------------------------------------------------------------%
+
+:- pred output(int::in, io__state::di, io__state::uo) is det.
+
+output(X) -->
+	io__write_int(X),
+	io__write_string("\n").
+
+:- pred outputs(list(int)::in, io__state::di, io__state::uo) is det.
+
+outputs(Xs) -->
+	outputs1(Xs),
+	io__write_string("\n").
+
+:- pred outputs1(list(int)::in, io__state::di, io__state::uo) is det.
+
+outputs1([]) --> [].
+outputs1([X | Xs]) -->
+	io__write_int(X),
+	io__write_string(" "),
+	outputs1(Xs).
cvs diff: Diffing tests/debugger/declarative
Index: tests/debugger/declarative/throw.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/declarative/throw.exp,v
retrieving revision 1.2
diff -u -r1.2 throw.exp
--- tests/debugger/declarative/throw.exp	2000/08/18 10:59:40	1.2
+++ tests/debugger/declarative/throw.exp	2000/10/09 08:45:46
@@ -9,7 +9,7 @@
 mdb> continue
        2:      2  2 CALL pred throw:p/1-0 (cc_nondet) throw.m:20
 mdb> finish
-      31:      2  2 EXCP pred throw:p/1-0 (cc_nondet) throw.m:22
+      31:      2  2 EXCP pred throw:p/1-0 (cc_nondet) q!;c2; throw.m:22
 mdb> dd
 Call p(_)
 Throws "Too big"
@@ -23,7 +23,7 @@
 p(_)
 "Too big"
 Is this a bug? yes
-      31:      2  2 EXCP pred throw:p/1-0 (cc_nondet) throw.m:22
+      31:      2  2 EXCP pred throw:p/1-0 (cc_nondet) q!;c2; throw.m:22
 mdb> continue
 mdb: warning: reached unknown label
 This may result in some exception events
@@ -31,7 +31,7 @@
 exception(univ("Too big" : string))
       32:      6  2 CALL pred throw:q/1-0 (semidet) throw.m:48
 mdb> finish
-      65:      6  2 EXCP pred throw:q/1-0 (semidet) throw.m:52
+      65:      6  2 EXCP pred throw:q/1-0 (semidet) c2;~;q!;c2;~;c2;q!;c1; throw.m:52
 mdb> dd
 Call q(_)
 Throws "Too big"
@@ -45,7 +45,7 @@
 q(_)
 "Too big"
 Is this a bug? yes
-      65:      6  2 EXCP pred throw:q/1-0 (semidet) throw.m:52
+      65:      6  2 EXCP pred throw:q/1-0 (semidet) c2;~;q!;c2;~;c2;q!;c1; throw.m:52
 mdb> continue
 mdb: warning: reached unknown label
 This may result in some exception events
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
Index: trace/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.26
diff -u -r1.26 mercury_trace.c
--- trace/mercury_trace.c	2000/09/22 06:00:03	1.26
+++ trace/mercury_trace.c	2000/10/10 02:41:36
@@ -47,6 +47,7 @@
 #include "mercury_trace_internal.h"
 #include "mercury_trace_external.h"
 #include "mercury_trace_spy.h"
+#include "mercury_trace_util.h"
 
 #include <stdio.h>
 
@@ -62,10 +63,32 @@
 Code 		*MR_trace_real(const MR_Stack_Layout_Label *layout);
 static	Code	*MR_trace_event(MR_Trace_Cmd_Info *cmd, bool interactive,
 			const MR_Stack_Layout_Label *layout,
-			MR_Trace_Port port, Unsigned seqno, Unsigned depth);
+			MR_Trace_Port port, MR_Unsigned seqno,
+			MR_Unsigned depth);
+static	const MR_Stack_Layout_Label *MR_unwind_stacks_for_retry(
+			const MR_Stack_Layout_Label *top_layout,
+			int ancestor_level, MR_Word **base_sp_ptr,
+			MR_Word **base_curfr_ptr, MR_Word **base_maxfr_ptr,
+			const char **problem);
+static	const char *MR_undo_updates_of_maxfr(const MR_Stack_Layout_Entry
+			*level_layout, MR_Word *sp, MR_Word *curfr,
+			MR_Word **maxfr_ptr);
 static	MR_Word	MR_trace_find_input_arg(const MR_Stack_Layout_Label *label, 
-			MR_Word *saved_regs, MR_uint_least16_t var_num,
-			bool *succeeded);
+			MR_Word *saved_regs,
+			MR_Word *base_sp, MR_Word *base_curfr,
+			MR_uint_least16_t var_num, bool *succeeded);
+
+#ifdef	MR_USE_MINIMAL_MODEL
+static	MR_Retry_Result MR_check_minimal_model_calls(MR_Event_Info *event_info,
+			int ancestor_level, MR_Word *target_maxfr,
+			const char **problem);
+#endif
+
+static	void	MR_init_call_table_array(void);
+static	void	MR_maybe_record_call_table(const MR_Stack_Layout_Entry
+			*level_layout, MR_Word *sp, MR_Word *curfr);
+static	void	MR_reset_call_table_array(void);
+static	void	MR_abandon_call_table_array(void);
 
 /*
 ** Reserve room for event counts for this many depths initially.
@@ -82,9 +105,9 @@
 Code *
 MR_trace_real(const MR_Stack_Layout_Label *layout)
 {
-	MR_Integer		maybe_from_full;
-	Unsigned	seqno;
-	Unsigned	depth;
+	MR_Integer	maybe_from_full;
+	MR_Unsigned	seqno;
+	MR_Unsigned	depth;
 	MR_Spy_Action	action;
 	bool		match;
 	MR_Trace_Port	port;
@@ -98,15 +121,15 @@
 			return NULL;
 		}
 
-		seqno = (Unsigned) MR_call_num_stackvar(MR_sp);
-		depth = (Unsigned) MR_call_depth_stackvar(MR_sp);
+		seqno = (MR_Unsigned) MR_call_num_stackvar(MR_sp);
+		depth = (MR_Unsigned) MR_call_depth_stackvar(MR_sp);
 	} else {
 		if (maybe_from_full > 0 && ! MR_framevar(maybe_from_full)) {
 			return NULL;
 		}
 
-		seqno = (Unsigned) MR_call_num_framevar(MR_curfr);
-		depth = (Unsigned) MR_call_depth_framevar(MR_curfr);
+		seqno = (MR_Unsigned) MR_call_num_framevar(MR_curfr);
+		depth = (MR_Unsigned) MR_call_depth_framevar(MR_curfr);
 	}
 
 	MR_trace_event_number++;
@@ -147,6 +170,7 @@
 			if (MR_trace_ctrl.MR_trace_stop_depth != depth) {
 				goto check_stop_print;
 			} else {
+				port = (MR_Trace_Port) layout->MR_sll_port;
 				return MR_trace_event(&MR_trace_ctrl,
 					TRUE, layout, port,
 					seqno, depth);
@@ -167,6 +191,23 @@
 				}
 			}
 
+		case MR_CMD_FAIL:
+			if (MR_trace_ctrl.MR_trace_stop_depth != depth) {
+				goto check_stop_print;
+			} else {
+				port = (MR_Trace_Port) layout->MR_sll_port;
+
+				if (port == MR_PORT_FAIL ||
+					port == MR_PORT_EXCEPTION)
+				{
+					return MR_trace_event(&MR_trace_ctrl,
+						TRUE, layout, port,
+						seqno, depth);
+				} else {
+					goto check_stop_print;
+				}
+			}
+
 		case MR_CMD_RESUME_FORWARD:
 			port = (MR_Trace_Port) layout->MR_sll_port;
 			if (port != MR_PORT_REDO &&
@@ -285,8 +326,8 @@
 static Code *
 MR_trace_interrupt(const MR_Stack_Layout_Label *layout)
 {
-	Unsigned	seqno;
-	Unsigned	depth;
+	MR_Unsigned	seqno;
+	MR_Unsigned	depth;
 	MR_Trace_Port	port;
 
 	/* restore the original MR_trace_func_ptr value */
@@ -300,11 +341,11 @@
 	restore_transient_registers();
 
 	if (MR_DETISM_DET_STACK(layout->MR_sll_entry->MR_sle_detism)) {
-		seqno = (Unsigned) MR_call_num_stackvar(MR_sp);
-		depth = (Unsigned) MR_call_depth_stackvar(MR_sp);
+		seqno = (MR_Unsigned) MR_call_num_stackvar(MR_sp);
+		depth = (MR_Unsigned) MR_call_depth_stackvar(MR_sp);
 	} else {
-		seqno = (Unsigned) MR_call_num_framevar(MR_curfr);
-		depth = (Unsigned) MR_call_depth_framevar(MR_curfr);
+		seqno = (MR_Unsigned) MR_call_num_framevar(MR_curfr);
+		depth = (MR_Unsigned) MR_call_depth_framevar(MR_curfr);
 	}
 	port = (MR_Trace_Port) layout->MR_sll_port;
 
@@ -330,7 +371,7 @@
 static Code *
 MR_trace_event(MR_Trace_Cmd_Info *cmd, bool interactive,
 	const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
-	Unsigned seqno, Unsigned depth)
+	MR_Unsigned seqno, MR_Unsigned depth)
 {
 	Code		*jumpaddr;
 	MR_Event_Info	event_info;
@@ -392,12 +433,22 @@
 	return jumpaddr;
 }
 
-const char *
+/*****************************************************************************/
+
+/* The initial size of arrays of argument values. */
+#define	MR_INIT_ARG_COUNT	20
+
+MR_Retry_Result
 MR_trace_retry(MR_Event_Info *event_info, MR_Event_Details *event_details,
-	Code **jumpaddr)
+	int ancestor_level, const char **problem, Code **jumpaddr)
 {
-	const MR_Stack_Layout_Entry	*entry;
+	MR_Word				*base_sp;
+	MR_Word				*base_curfr;
+	MR_Word				*base_maxfr;
+	const MR_Stack_Layout_Label	*top_layout;
+	const MR_Stack_Layout_Label	*return_label_layout;
 	const MR_Stack_Layout_Label	*call_label;
+	const MR_Stack_Layout_Entry	*level_layout;
 	const MR_Stack_Layout_Vars	*input_args;
 	MR_Word				*args;
 	int				arg_max;
@@ -405,23 +456,52 @@
 	MR_Word				arg_value;
 	int				i;
 	bool				succeeded;
-	const char			*message;
-	MR_Word 				*saved_regs;
+	MR_Word 			*saved_regs;
+#ifdef	MR_USE_MINIMAL_MODEL
+	MR_Retry_Result			result;
+#endif
 
+	args = NULL;
+	MR_init_call_table_array();
+
 	saved_regs = event_info->MR_saved_regs;
-	entry = event_info->MR_event_sll->MR_sll_entry;
-	if (!MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
-		message = "Cannot perform retry, because this procedure "
-			"was not compiled with\nexecution tracing enabled.";
-		return message;
+#ifdef	MR_DEBUG_RETRY
+	MR_print_stack_regs(stdout, saved_regs);
+#endif
+
+	top_layout = event_info->MR_event_sll;
+	*problem = NULL;
+	base_sp = MR_saved_sp(saved_regs);
+	base_curfr = MR_saved_curfr(saved_regs);
+	base_maxfr = MR_saved_maxfr(saved_regs);
+	return_label_layout = MR_unwind_stacks_for_retry(top_layout,
+			ancestor_level, &base_sp, &base_curfr, &base_maxfr,
+			problem);
+#ifdef	MR_DEBUG_RETRY
+	MR_print_stack_regs(stdout, saved_regs);
+#endif
+
+	if (return_label_layout == NULL) {
+		if (*problem == NULL) {
+			*problem = "MR_unwind_stacks_for_retry failed "
+					"without reporting a problem";
+		}
+
+		goto report_problem;
+	}
+
+	level_layout = return_label_layout->MR_sll_entry;
+	if (! MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(level_layout)) {
+		*problem = "that procedure does not have debugging information";
+		goto report_problem;
 	}
 
-	call_label = entry->MR_sle_call_label;
+	call_label = level_layout->MR_sle_call_label;
 	input_args = &call_label->MR_sll_var_info;
 	if (input_args->MR_slvs_var_count < 0) {
-		message = "Cannot perform retry because information about "
+		*problem = "Cannot perform retry because information about "
 		          "the input arguments is not available.";
-		return message;
+		goto report_problem;
 	}
 
 	/*
@@ -432,19 +512,18 @@
 	** no native garbage collection can be triggered.
 	*/
 
-	args = NULL;
 	arg_max = 0;
 
 	for (i = 0; i < MR_all_desc_var_count(input_args); i++) {
-		arg_value = MR_trace_find_input_arg(event_info->MR_event_sll,
-				saved_regs,
+		arg_value = MR_trace_find_input_arg(return_label_layout,
+				saved_regs, base_sp, base_curfr,
 				input_args->MR_slvs_var_nums[i],
 				&succeeded);
 
 		if (! succeeded) {
-			message = "Cannot perform retry because the values of "
-				  "some input arguments are missing.";
-			return message;
+			*problem = "Cannot perform retry because the values "
+				  "of some input arguments are missing.";
+			goto report_problem;
 		}
 
 		if (i < MR_long_desc_var_count(input_args)) {
@@ -463,43 +542,82 @@
 			MR_fatal_error("illegal location for input argument");
 		}
 	}
+
+#ifdef	MR_USE_MINIMAL_MODEL
 
-	MR_trace_call_seqno = event_info->MR_call_seqno - 1;
-	MR_trace_call_depth = event_info->MR_call_depth - 1;
+	result = MR_check_minimal_model_calls(event_info, ancestor_level,
+			base_maxfr, problem);
 
-	if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+	switch (result) {
+	case MR_RETRY_OK_DIRECT:
+		/* we just go on to the code below */
+		break;
+
+	case MR_RETRY_OK_FINISH_FIRST:
+	case MR_RETRY_OK_FAIL_FIRST:
+		MR_abandon_call_table_array();
+		return result;
+
+	case MR_RETRY_ERROR:
+	default:
+		if (*problem == NULL) {
+			*problem = "MR_check_minimal_model_calls failed "
+					"without reporting problem";
+		}
+
+		goto report_problem;
+	}
+
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+	/*
+	** At this point, we are now sure that we can carry out the retry
+	** operation directly. Before we were sure, we couldn't modify the
+	** environment (i.e. the stacks, the saved registers, and the relevant
+	** call tables). Now, however, we can set up the environment to make
+	** it reflect its state at the time of the entry to the retried call.
+	*/
+
+	MR_saved_sp(saved_regs) = base_sp;
+	MR_saved_curfr(saved_regs) = base_curfr;
+	MR_saved_maxfr(saved_regs) = base_maxfr;
+
+	if (MR_DETISM_DET_STACK(level_layout->MR_sle_detism)) {
 		MR_Long_Lval	location;
 		MR_Word		*this_frame;
-
-		/*
-		** We are at a final port, so both curfr and maxfr
-		** must already have been reset to their original values.
-		** We only need to set up the succip register for the "call",
-		** and then remove this frame from the det stack.
-		*/
 
-		location = entry->MR_sle_succip_locn;
+		location = level_layout->MR_sle_succip_locn;
 		if (MR_LONG_LVAL_TYPE(location) != MR_LONG_LVAL_TYPE_STACKVAR)
 		{
 			MR_fatal_error("illegal location for stored succip");
 		}
 
 		this_frame = MR_saved_sp(saved_regs);
+#ifdef	MR_DEBUG_RETRY
+		MR_print_succip_reg(stdout, saved_regs);
+		MR_print_stack_regs(stdout, saved_regs);
+#endif
 		MR_saved_succip(saved_regs) = (MR_Word *)
 				MR_based_stackvar(this_frame,
 				MR_LONG_LVAL_NUMBER(location));
-		MR_saved_sp(saved_regs) -= entry->MR_sle_stack_slots;
+		MR_saved_sp(saved_regs) -= level_layout->MR_sle_stack_slots;
+#ifdef	MR_DEBUG_RETRY
+		MR_print_succip_reg(stdout, saved_regs);
+		MR_print_stack_regs(stdout, saved_regs);
+#endif
 		MR_trace_event_number = MR_event_num_stackvar(this_frame);
+		MR_trace_call_seqno = MR_call_num_stackvar(this_frame) - 1;
+		MR_trace_call_depth = MR_call_depth_stackvar(this_frame) - 1;
 
 #ifdef	MR_USE_TRAIL
-		if (entry->MR_sle_maybe_trail >= 0) {
+		if (level_layout->MR_sle_maybe_trail >= 0) {
 			MR_Word	ticket_counter;
 			MR_Word	trail_ptr;
 
 			trail_ptr = MR_based_stackvar(this_frame,
-					entry->MR_sle_maybe_trail);
+					level_layout->MR_sle_maybe_trail);
 			ticket_counter = MR_based_stackvar(this_frame,
-					entry->MR_sle_maybe_trail+1);
+					level_layout->MR_sle_maybe_trail+1);
 			MR_reset_ticket(trail_ptr, MR_retry);
 			MR_discard_tickets_to(ticket_counter);
 		} else {
@@ -509,29 +627,31 @@
 	} else {
 		MR_Word	*this_frame;
 
-		/*
-		** We are at a final port, so sp must already have been reset
-		** to its original value. We only need to set up the succip
-		** and curfr registers for the "call", and remove this frame,
-		** and any other frames above it, from the nondet stack.
-		*/
-
 		this_frame = MR_saved_curfr(saved_regs);
-
+#ifdef	MR_DEBUG_RETRY
+		MR_print_succip_reg(stdout, saved_regs);
+		MR_print_stack_regs(stdout, saved_regs);
+#endif
 		MR_saved_succip(saved_regs) = MR_succip_slot(this_frame);
 		MR_saved_curfr(saved_regs) = MR_succfr_slot(this_frame);
 		MR_saved_maxfr(saved_regs) = MR_prevfr_slot(this_frame);
+#ifdef	MR_DEBUG_RETRY
+		MR_print_succip_reg(stdout, saved_regs);
+		MR_print_stack_regs(stdout, saved_regs);
+#endif
 		MR_trace_event_number = MR_event_num_framevar(this_frame);
+		MR_trace_call_seqno = MR_call_num_framevar(this_frame) - 1;
+		MR_trace_call_depth = MR_call_depth_framevar(this_frame) - 1;
 
 #ifdef	MR_USE_TRAIL
-		if (entry->MR_sle_maybe_trail >= 0) {
+		if (level_layout->MR_sle_maybe_trail >= 0) {
 			MR_Word	ticket_counter;
 			MR_Word	trail_ptr;
 
 			trail_ptr = MR_based_framevar(this_frame,
-					entry->MR_sle_maybe_trail);
+					level_layout->MR_sle_maybe_trail);
 			ticket_counter = MR_based_framevar(this_frame,
-					entry->MR_sle_maybe_trail+1);
+					level_layout->MR_sle_maybe_trail+1);
 			MR_reset_ticket(trail_ptr, MR_retry);
 			MR_discard_tickets_to(ticket_counter);
 		} else {
@@ -544,12 +664,8 @@
 		saved_reg(saved_regs, i) = args[i];
 	}
 
-	if (args != NULL) {
-		free(args);
-	}
-
 	event_info->MR_max_mr_num = max(event_info->MR_max_mr_num, arg_max);
-	*jumpaddr = entry->MR_sle_code_addr;
+	*jumpaddr = level_layout->MR_sle_code_addr;
 
 	/*
 	** Overriding MR_trace_call_seqno etc is not enough, because
@@ -561,13 +677,128 @@
 	event_details->MR_call_depth = MR_trace_call_depth;
 	event_details->MR_event_number = MR_trace_event_number;
 
-	return NULL;
+	if (args != NULL) {
+		MR_free(args);
+	}
+
+	MR_reset_call_table_array();
+#ifdef	MR_DEBUG_RETRY
+	MR_print_stack_regs(stdout, saved_regs);
+#endif
+	return MR_RETRY_OK_DIRECT;
+
+report_problem:
+	if (args != NULL) {
+		MR_free(args);
+	}
+
+	MR_abandon_call_table_array();
+	return MR_RETRY_ERROR;
+}
+
+/*
+** This function figures out the state of the stacks (i.e. the values of sp,
+** curfr and maxfr) just after entry to the procedure specified by the given
+** ancestor level, and returns the proc layout for the specified procedure.
+** It also
+**
+** If it finds that it cannot do its job, it returns NULL and sets *problem
+** to point to a string giving the reason for its failure.
+*/
+
+static const MR_Stack_Layout_Label *
+MR_unwind_stacks_for_retry(const MR_Stack_Layout_Label *top_layout,
+	int ancestor_level, MR_Word **sp_ptr, MR_Word **curfr_ptr,
+	MR_Word **maxfr_ptr, const char **problem)
+{
+	MR_Stack_Walk_Step_Result       result;
+	const MR_Stack_Layout_Entry	*level_layout;
+	const MR_Stack_Layout_Label	*return_label_layout;
+	int				i;
+
+	if (ancestor_level < 0) {
+		*problem = "no such stack frame";
+		return NULL;
+	}
+
+	return_label_layout = top_layout;
+	level_layout = top_layout->MR_sll_entry;
+	*problem = MR_undo_updates_of_maxfr(level_layout,
+			*sp_ptr, *curfr_ptr, maxfr_ptr);
+
+	if (*problem != NULL) {
+		return NULL;
+	}
+
+	MR_maybe_record_call_table(level_layout, *sp_ptr, *curfr_ptr);
+
+	for (i = 0; i < ancestor_level; i++) {
+		result = MR_stack_walk_step(level_layout, &return_label_layout,
+				sp_ptr, curfr_ptr, problem);
+		if (result != STEP_OK) {
+			if (*problem == NULL) {
+				*problem = "not that many ancestors";
+			}
+
+			return NULL;
+		}
+
+		level_layout = return_label_layout->MR_sll_entry;
+		*problem = MR_undo_updates_of_maxfr(level_layout,
+				*sp_ptr, *curfr_ptr, maxfr_ptr);
+
+		if (*problem != NULL) {
+			return NULL;
+		}
+
+		MR_maybe_record_call_table(level_layout, *sp_ptr, *curfr_ptr);
+	}
+
+	return return_label_layout;
 }
 
+static const char *
+MR_undo_updates_of_maxfr(const MR_Stack_Layout_Entry *level_layout,
+	MR_Word *level_sp, MR_Word *level_curfr, MR_Word **maxfr_ptr)
+{
+	if (MR_DETISM_DET_STACK(level_layout->MR_sle_detism)) {
+		/*
+		** The code of a procedure that lives on the det stack
+		** never updates curfr, but may update maxfr by pushing
+		** a temporary nondet frame. If it does so, and the
+		** procedure is traced, the original value of maxfr 
+		** will be saved in a stack slot.
+		*/
+
+		if (! MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(level_layout)) {
+			return "an intervening stack frame "
+				"has no debugging information";
+		} else if (level_layout->MR_sle_maybe_maxfr > 0) {
+			*maxfr_ptr = (MR_Word *) MR_based_stackvar(level_sp,
+				level_layout->MR_sle_maybe_maxfr);
+#if MR_DEBUG_RETRY
+			fprintf(stdout, "resetting maxfr to ");
+			MR_print_nondstackptr(stdout, *maxfr_ptr);
+			fprintf(stdout, "\n");
+#endif
+		} /* else we need do nothing */
+	} else {
+		/*
+		** When we finish setting up the stack frame of a
+		** procedure that lives on the nondet stack,
+		** maxfr == curfr.
+		*/
+
+		*maxfr_ptr = level_curfr;
+	}
 
+	return NULL;
+}
+
 static MR_Word
 MR_trace_find_input_arg(const MR_Stack_Layout_Label *label, MR_Word *saved_regs,
-	MR_uint_least16_t var_num, bool *succeeded)
+	MR_Word *base_sp, MR_Word *base_curfr, MR_uint_least16_t var_num,
+	bool *succeeded)
 {
 	const MR_Stack_Layout_Vars	*vars;
 	int				i;
@@ -583,17 +814,307 @@
 			if (i < MR_long_desc_var_count(vars)) {
 				return MR_lookup_long_lval_base(
 					MR_long_desc_var_locn(vars, i),
-					saved_regs, MR_saved_sp(saved_regs),
-					MR_saved_curfr(saved_regs), succeeded);
+					saved_regs, base_sp, base_curfr,
+					succeeded);
 			} else {
 				return MR_lookup_short_lval_base(
 					MR_short_desc_var_locn(vars, i),
-					saved_regs, MR_saved_sp(saved_regs),
-				MR_saved_curfr(saved_regs), succeeded);
+					saved_regs, base_sp, base_curfr,
+					succeeded);
 			}
 		}
 	}
 
 	*succeeded = FALSE;
 	return 0;
+}
+
+/*****************************************************************************/
+
+#ifdef	MR_USE_MINIMAL_MODEL
+
+/*
+** MR_check_minimal_model_calls scans the nondet stack region about to be
+** discarded by the retry operation, searching for the stack frames of
+** procedures whose evaluation method is minimal model.
+**
+** In grades that do enable minimal model tabling, redoip hijacking is
+** disabled, so the fact that the redoip slot of a nondet stack frame points
+** to a label within a given procedure means that the frame was created by that
+** procedure.
+**
+** If we ever get here, the redoip slot of the home frame of every model_non
+** procedure compiled with debugging ought to point to a label in its own code,
+** not to a label in the runtime system.
+*/
+
+#define	INIT_RECORD_ARRAY_SIZE		10
+
+typedef	struct {
+	MR_Subgoal	*record_subgoal;
+	MR_Subgoal	*record_leader;
+	bool		found_leader_generator;
+} MR_Minimal_Model_Record;
+
+static MR_Retry_Result
+MR_check_minimal_model_calls(MR_Event_Info *event_info, int ancestor_level,
+	MR_Word *target_maxfr, const char **problem)
+{
+	const MR_Stack_Layout_Label	*label_layout;
+	const MR_Stack_Layout_Entry	*proc_layout;
+	MR_Word				*top_maxfr;
+	MR_Word				*cur_maxfr;
+	Code				*redoip;
+	MR_TrieNode			trienode;
+	MR_Subgoal			*subgoal;
+	MR_Subgoal			*leader;
+	MR_Minimal_Model_Record		*record_ptrs;
+	int				record_ptr_max;
+	int				record_ptr_next;
+	int				frame_size;
+	int				cur_gen;
+	MR_Internal			*label;
+	int				i;
+	bool				any_missing_generators;
+
+	top_maxfr = MR_saved_maxfr(event_info->MR_saved_regs);
+	cur_gen = MR_gen_next - 1;
+
+	for (cur_maxfr = top_maxfr;
+		cur_maxfr > target_maxfr;
+		cur_maxfr = MR_prevfr_slot(cur_maxfr))
+	{
+		frame_size = cur_maxfr - MR_prevfr_slot(cur_maxfr);
+		if (frame_size == MR_NONDET_TEMP_SIZE) {
+			/*
+			** These frames represent auxiliary frames of model_non
+			** procedures. We will traverse the main frame of every
+			** such procedure as well, and we can do everything we
+			** need to do then, so we can ignore these frames.
+			*/
+
+			continue;
+		} else if (frame_size == MR_DET_TEMP_SIZE) {
+			/*
+			** These frames represent auxiliary frames of model_det
+			** or model_semi procedures, which call a model_non
+			** procedure inside a commit. We should queue the
+			** associated commit stack entry for resetting,
+			** but the future of the commit stack is in flux
+			** at the moment (it has some design-level bugs),
+			** so for now we just note the need for future work
+			** here XXX.
+			*/
+
+			continue;
+		}
+
+		/*
+		** The remaining frames represent the main frames of model_non
+		** procedures.
+		*/
+
+		redoip = MR_prevfr_slot(cur_maxfr);
+		label = MR_lookup_internal_by_addr(redoip);
+		if (label == NULL) {
+			*problem = "reached unknown label ";
+			return MR_RETRY_ERROR;
+		}
+
+		if (label->i_layout == NULL) {
+			*problem = "reached label without debugging info";
+			return MR_RETRY_ERROR;
+		}
+
+		label_layout = label->i_layout;
+		proc_layout = label_layout->MR_sll_entry;
+
+		if (! MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(proc_layout)) {
+			*problem = "reached label without debugging info";
+			return MR_RETRY_ERROR;
+		}
+
+		if (proc_layout->MR_sle_eval_method != MR_EVAL_METHOD_MINIMAL)
+		{
+			continue;
+		}
+
+		if (proc_layout->MR_sle_maybe_call_table <= 0) {
+			fatal_error("minimal model procedure "
+					"has no call table slot");
+		}
+
+		trienode = (MR_TrieNode) MR_based_framevar(cur_maxfr, 
+					proc_layout->MR_sle_maybe_call_table);
+		subgoal = trienode->MR_subgoal;
+		if (subgoal->leader != NULL) {
+			leader = subgoal->leader;
+		} else {
+			leader = subgoal;
+		}
+
+		MR_ensure_room_for_next(record_ptr, MR_Minimal_Model_Record,
+			INIT_RECORD_ARRAY_SIZE);
+
+		record_ptrs[record_ptr_next].record_subgoal = subgoal;
+		record_ptrs[record_ptr_next].record_leader = leader;
+		record_ptrs[record_ptr_next].found_leader_generator = FALSE;
+		record_ptr_next++;
+
+		if (cur_maxfr == MR_gen_stack[cur_gen].generator_frame) {
+			for (i = 0; i < record_ptr_next; i++) {
+				if (record_ptrs[i].record_leader == subgoal) {
+					record_ptrs[i].found_leader_generator
+						= TRUE;
+				}
+			}
+
+			cur_gen--;
+		}
+	}
+
+	any_missing_generators = FALSE;
+	for (i = 0; i < record_ptr_next; i++) {
+		if (! record_ptrs[i].found_leader_generator) {
+			any_missing_generators = TRUE;
+		}
+	}
+
+	if (any_missing_generators) {
+		*problem = "retry would interfere with minimal model tabling";
+		return MR_RETRY_ERROR;
+	} else if (record_ptr_next > 0) {
+		if (event_info->MR_trace_port == MR_PORT_EXCEPTION
+		&& ancestor_level == 0)
+		{
+			*problem = "cannot retry minimal model procedure "
+				"from the exception port";
+			return MR_RETRY_ERROR;
+		}
+
+		label_layout = event_info->MR_event_sll;
+		proc_layout = label_layout->MR_sll_entry;
+
+		if (proc_layout->MR_sle_eval_method == MR_EVAL_METHOD_MINIMAL) {
+			return MR_RETRY_OK_FAIL_FIRST;
+		} else {
+			return MR_RETRY_OK_FINISH_FIRST;
+		}
+	} else {
+		return MR_RETRY_OK_DIRECT;
+	}
+}
+
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+/*****************************************************************************/
+
+/*
+** The rest of this file implements the mechanism that the retry command uses
+** to reset the call tables of any calls being retried over.
+**
+** Each execution of MR_trace_retry is required to make the following
+** sequence of calls on this submodule:
+**
+**	one call to MR_init_call_table_array
+**	zero or more calls to MR_maybe_record_call_table
+**	one call to either
+**		MR_reset_call_table_array (if the direct retry is successful)
+**		MR_abandon_call_table_array (if it is not)
+*/
+
+static	MR_TrieNode	*MR_call_table_ptrs;
+static	int		MR_call_table_ptr_max;
+static	int		MR_call_table_ptr_next;
+
+#define	INIT_CALL_TABLE_ARRAY_SIZE	10
+
+static void
+MR_init_call_table_array(void)
+{
+	MR_call_table_ptr_next = 0;
+}
+
+static void
+MR_maybe_record_call_table(const MR_Stack_Layout_Entry *level_layout,
+	MR_Word *sp, MR_Word *curfr)
+{
+	MR_TrieNode	call_table;
+
+	if (! MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(level_layout)) {
+		/*
+		** The exec trace seems to have disappeared since the call
+		** to MR_undo_updates_of_maxfr ...
+		*/
+
+		fatal_error("proc layout without exec trace "
+				"in MR_maybe_record_call_table");
+	}
+
+	switch (level_layout->MR_sle_eval_method) {
+
+	case MR_EVAL_METHOD_NORMAL:
+		/* nothing to do */
+		return;
+
+	case MR_EVAL_METHOD_MEMO:
+	case MR_EVAL_METHOD_LOOP_CHECK:
+		if (MR_DETISM_DET_STACK(level_layout->MR_sle_detism)) {
+			call_table = (MR_TrieNode) MR_based_stackvar(sp, 
+				level_layout->MR_sle_maybe_call_table);
+		} else {
+			call_table = (MR_TrieNode) MR_based_framevar(curfr, 
+				level_layout->MR_sle_maybe_call_table);
+		}
+
+		if (call_table != NULL) {
+			MR_ensure_room_for_next(MR_call_table_ptr, MR_TrieNode,
+				INIT_CALL_TABLE_ARRAY_SIZE);
+
+			MR_call_table_ptrs[MR_call_table_ptr_next] =
+				call_table;
+			MR_call_table_ptr_next++;
+		}
+
+		return;
+
+	case MR_EVAL_METHOD_MINIMAL:
+		/*
+		** We want to process all the minimal model calls whose
+		** stack frames are in the part of the nondet stack to be
+		** removed by the retry operation, not just those which are
+		** direct ancestors of the current call. Such calls are
+		** therefore processed in MR_check_minimal_model_calls,
+		** not here.
+		*/
+
+		return;
+	}
+
+	fatal_error("unknown evaluation method in MR_maybe_record_call_table");
+}
+
+static void
+MR_reset_call_table_array(void)
+{
+	int	i;
+
+	for (i = 0; i < MR_call_table_ptr_next; i++) {
+#ifdef	MR_DEBUG_RETRY
+		printf("resetting call table ptr %d (%x)\n",
+			(MR_Integer) MR_call_table_ptrs[i],
+			(MR_Integer) MR_call_table_ptrs[i]);
+#endif
+		MR_call_table_ptrs[i]->MR_integer = 0;
+	}
+
+	MR_abandon_call_table_array();
+}
+
+static void
+MR_abandon_call_table_array(void)
+{
+	if (MR_call_table_ptrs != NULL) {
+		MR_free(MR_call_table_ptrs);
+	}
 }
Index: trace/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.h,v
retrieving revision 1.15
diff -u -r1.15 mercury_trace.h
--- trace/mercury_trace.h	2000/08/08 04:58:38	1.15
+++ trace/mercury_trace.h	2000/10/04 17:08:37
@@ -28,9 +28,9 @@
 */
 
 typedef struct MR_Event_Info_Struct {
-	Unsigned			MR_event_number;
-	Unsigned			MR_call_seqno;
-	Unsigned			MR_call_depth;
+	MR_Unsigned			MR_event_number;
+	MR_Unsigned			MR_call_seqno;
+	MR_Unsigned			MR_call_depth;
 	MR_Trace_Port			MR_trace_port;
 	const MR_Stack_Layout_Label	*MR_event_sll;
 	const char 			*MR_event_path;
@@ -45,16 +45,75 @@
 */
 
 typedef struct MR_Event_Details_Struct {
-	int			MR_call_seqno;
-	int			MR_call_depth;
-	int			MR_event_number;
+	MR_Unsigned			MR_event_number;
+	MR_Unsigned			MR_call_seqno;
+	MR_Unsigned			MR_call_depth;
 } MR_Event_Details;
 
-/* The initial size of arrays of argument values. */
-#define	MR_INIT_ARG_COUNT	20
+/*
+** The above declarations are part of the interface between MR_trace_real
+** and the internal and external debuggers. Even though MR_trace_real is
+** defined in mercury_trace.c, its prototype is not here. Instead, it is
+** in runtime/mercury_init.h. This is necessary because the address of
+** MR_trace_real may be taken in automatically generated <main>_init.c files,
+** and we do not want to include mercury_trace.h in such files; we don't want
+** them to refer to the trace directory at all unless debugging is enabled.
+*/
+
+/*
+** Ideally, MR_trace_retry works by resetting the state of the stacks and
+** registers to the state appropriate for the call to the selected ancestor,
+** setting *jumpaddr to point to the start of the code for the selected
+** ancestor, and returning MR_RETRY_OK_DIRECT.
+**
+** If resetting the stacks requires discarding the stack frame of a procedure
+** whose evaluation method is memo or loopcheck, we must also reset the call
+** table entry for that particular call to uninitialized. There are two reasons
+** for this. The first is that the call table entry was uninitialized at the
+** time of the first call, so if the retried call is to do what the original
+** call did, it must find the call table entry in the same state. The second
+** reason is that if we did not reset the call table entry, then the retried
+** call would find the "call active" marker left by the original call, and
+** since this normally indicates an infinite loop, it will generate a runtime
+** abort.
+**
+** Unfortunately, resetting the call table entry to uninitialized does not work
+** in general for procedures whose evaluation method is minimal model tabling.
+** In such procedures, a subgoal can be a consumer as well as a generator,
+** and control passes between consumers and generators in a complex fashion.
+** There is no safe way to reset the state of such a system, except to wait
+** for normal forward execution to execute the completion operation on an
+** SCC of mutually dependent subgoals.
+**
+** If the stack segments between the current call and the call to be retried
+** contain one or more such complete SCCs, then MR_trace_retry will return
+** either MR_RETRY_OK_FINISH_FIRST or MR_RETRY_OK_FAIL_FIRST. The first
+** indicates that the `retry' command should be executed only after a `finish'
+** command on the selected call has made the state of the SCC quiescent.
+** However, if the selected call is itself a generator, then reaching one of
+** its exit ports is not enough to make its SCC quiescent; for that, one must
+** wait for its failure. This is why in such cases, MR_trace_retry will ask
+** for the `retry' command to be executed only after a `fail' command.
+** 
+** If the fail command reaches an exception port on the selected call instead
+** of the fail port, then the SCC cannot be made quiescent, and MR_trace_retry
+** will return MR_RETRY_ERROR, putting a description of the error into
+** *problem. It will also do this for other, more prosaic problems, such as
+** when it finds that some of the stack frames it looks at lack debugging
+** information.
+*/
 
-extern	const char *MR_trace_retry(MR_Event_Info *event_info,
-			MR_Event_Details *event_details, Code **jumpaddr);
+typedef	enum {
+	MR_RETRY_OK_DIRECT,
+	MR_RETRY_OK_FINISH_FIRST,
+	MR_RETRY_OK_FAIL_FIRST,
+	MR_RETRY_ERROR
+} MR_Retry_Result;
+
+extern	MR_Retry_Result	MR_trace_retry(MR_Event_Info *event_info,
+				MR_Event_Details *event_details,
+				int ancestor_level, const char **problem,
+				Code **jumpaddr);
 
 /*
 ** MR_trace_cmd says what mode the tracer is in, i.e. how events should be
@@ -70,6 +129,9 @@
 ** event at depth MR_trace_stop_depth and whose port is EXIT or FAIL or
 ** EXCEPTION.
 **
+** If MR_trace_cmd == MR_CMD_FAIL, the event handler will stop at the next
+** event at depth MR_trace_stop_depth and whose port is FAIL or EXCEPTION.
+**
 ** If MR_trace_cmd == MR_CMD_RESUME_FORWARD, the event handler will stop at
 ** the next event of any call whose port is *not* REDO or FAIL or EXCEPTION.
 **
@@ -93,6 +155,7 @@
 	MR_CMD_GOTO,
 	MR_CMD_NEXT,
 	MR_CMD_FINISH,
+	MR_CMD_FAIL,
 	MR_CMD_RESUME_FORWARD,
 	MR_CMD_EXCP,
 	MR_CMD_RETURN,
@@ -114,12 +177,12 @@
 				** if MR_trace_cmd is MR_CMD_NEXT or
 				** MR_CMD_FINISH.
 				*/
-	Unsigned		MR_trace_stop_depth;
+	MR_Unsigned		MR_trace_stop_depth;
 				/*
 				** The MR_trace_stop_event field is meaningful
 				** if MR_trace_cmd is MR_CMD_GOTO  
 				*/
-	Unsigned		MR_trace_stop_event;
+	MR_Unsigned		MR_trace_stop_event;
 	MR_Trace_Print_Level	MR_trace_print_level;
 	bool			MR_trace_strict;
 
Index: trace/mercury_trace_declarative.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_declarative.c,v
retrieving revision 1.30
diff -u -r1.30 mercury_trace_declarative.c
--- trace/mercury_trace_declarative.c	2000/10/01 03:13:43	1.30
+++ trace/mercury_trace_declarative.c	2000/10/10 00:17:30
@@ -1135,6 +1135,7 @@
 		MR_Event_Info *event_info, MR_Event_Details *event_details,
 		Code **jumpaddr)
 {
+	MR_Retry_Result		result;
 	MR_Stack_Layout_Entry 	*entry;
 	FILE			*out;
 	Unsigned		depth_limit;
@@ -1232,14 +1233,20 @@
 		MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
 		MR_Event_Details *event_details, Code **jumpaddr)
 {
-	const char		*message;
+	const char		*problem;
+	MR_Retry_Result		retry_result;
 
 	/*
 	** Go back to an event before the topmost call.
 	*/
-	message = MR_trace_retry(event_info, event_details, jumpaddr);
-	if (message != NULL) {
-		return message;
+	retry_result = MR_trace_retry(event_info, event_details, 0, &problem,
+			jumpaddr);
+	if (retry_result != MR_RETRY_OK_DIRECT) {
+		if (retry_result == MR_RETRY_ERROR) {
+			return problem;
+		} else {
+			return "internal error: direct retry impossible";
+		}
 	}
 
 	/*
@@ -1330,7 +1337,8 @@
 MR_decl_handle_bug_found(Unsigned bug_event, MR_Trace_Cmd_Info *cmd,
 		MR_Event_Info *event_info, MR_Event_Details *event_details)
 {
-	const char		*message;
+	const char		*problem;
+	MR_Retry_Result		retry_result;
 	Code			*jumpaddr;
 
 	/*
@@ -1338,10 +1346,25 @@
 	** bug event.  Then set the command to go to the bug
 	** event and return to interactive mode.
 	*/
-	message = MR_trace_retry(event_info, event_details, &jumpaddr);
-	if (message != NULL) {
+#ifdef	MR_DEBUG_RETRY
+	MR_print_stack_regs(stdout, event_info->MR_saved_regs);
+	MR_print_succip_reg(stdout, event_info->MR_saved_regs);
+#endif
+	retry_result = MR_trace_retry(event_info, event_details, 0, &problem,
+			&jumpaddr);
+#ifdef	MR_DEBUG_RETRY
+	MR_print_stack_regs(stdout, event_info->MR_saved_regs);
+	MR_print_succip_reg(stdout, event_info->MR_saved_regs);
+	MR_print_r_regs(stdout, event_info->MR_saved_regs);
+#endif
+	if (retry_result != MR_RETRY_OK_DIRECT) {
 		fflush(MR_mdb_out);
-		fprintf(MR_mdb_err, "mdb: diagnosis aborted:\n%s\n", message);
+		fprintf(MR_mdb_err, "mdb: diagnosis aborted:\n");
+		if (retry_result == MR_RETRY_ERROR) {
+			fprintf(MR_mdb_err, "%s\n", problem);
+		} else {
+			fprintf(MR_mdb_err, "direct retry impossible\n");
+		}
 		MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
 		MR_trace_enabled = TRUE;
 		return MR_trace_event_internal(cmd, TRUE, event_info);
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.42
diff -u -r1.42 mercury_trace_external.c
--- trace/mercury_trace_external.c	2000/08/11 16:50:24	1.42
+++ trace/mercury_trace_external.c	2000/10/10 00:17:30
@@ -190,7 +190,7 @@
 			const MR_Stack_Layout_Entry *entry_layout, int count,
 			int start_level, MR_Word *base_sp, MR_Word *base_curfr,
 			const char *filename, int linenumber,
-			bool context_mismatch);
+			const char *goal_path, bool context_mismatch);
 static void	MR_get_list_modules_to_import(MR_Word debugger_request, 
 			MR_Integer *modules_list_length_ptr,
 			MR_Word *modules_list_ptr);
@@ -497,8 +497,9 @@
 	MR_Trace_Port	port = event_info->MR_trace_port;
 	const char	*path = event_info->MR_event_path;
 	MR_Word		*saved_regs = event_info->MR_saved_regs;
-	MR_Integer		modules_list_length;
+	MR_Integer	modules_list_length;
 	MR_Word		modules_list;
+	MR_Retry_Result	retry_result;
 	static MR_String	MR_object_file_name;
 
 	MR_trace_enabled = FALSE;
@@ -618,9 +619,9 @@
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_RETRY\n");
 				}
-				message = MR_trace_retry(event_info, 
-					&event_details, &jumpaddr);
-				if (message == NULL) {
+				retry_result = MR_trace_retry(event_info, 
+					&event_details, 0, &message, &jumpaddr);
+				if (retry_result == MR_RETRY_OK_DIRECT) {
 					MR_send_message_to_socket("ok");
 					cmd->MR_trace_cmd = MR_CMD_GOTO;
 					cmd->MR_trace_stop_event = 
@@ -1281,8 +1282,9 @@
 static void
 MR_dump_stack_record_print_to_socket(FILE *fp, 
 	const MR_Stack_Layout_Entry *entry_layout, int count, int start_level, 
-	MR_Word *base_sp, MR_Word *base_curfr, const char *filename, int linenumber,
-	bool context_mismatch)
+	MR_Word *base_sp, MR_Word *base_curfr,
+	const char *filename, int linenumber,
+	const char *goal_path, bool context_mismatch)
 {
 	MR_send_message_to_socket_format("level(%d).\n", start_level);
 	MR_print_proc_id_to_socket(entry_layout, NULL, base_sp, base_curfr);
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.81
diff -u -r1.81 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	2000/09/25 04:37:26	1.81
+++ trace/mercury_trace_internal.c	2000/10/10 00:17:30
@@ -155,10 +155,6 @@
 			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
 			MR_Event_Details *event_details, Code **jumpaddr);
 static	bool	MR_parse_source_locn(char *word, const char **file, int *line);
-static	void	MR_print_stack_regs(MR_Word *saved_regs);
-static	void	MR_print_heap_regs(MR_Word *saved_regs);
-static	void	MR_print_tabling_regs(MR_Word *saved_regs);
-static	void	MR_print_succip_reg(MR_Word *saved_regs);
 static	bool	MR_trace_options_strict_print(MR_Trace_Cmd_Info *cmd,
 			char ***words, int *word_count,
 			const char *cat, const char *item);
@@ -398,6 +394,11 @@
 			&base_sp, &base_curfr);
 		fprintf(MR_mdb_out, "%4d ", ancestor_level);
 		if (detailed) {
+			/*
+			** We want to print the trace info first regardless
+			** of the value of MR_context_position.
+			*/
+
 			MR_print_call_trace_info(MR_mdb_out, entry,
 				base_sp, base_curfr);
 			indent = 26;
@@ -405,8 +406,8 @@
 			indent = 5;
 		}
 
-		MR_print_proc_id_trace_and_context(MR_mdb_out,
-			MR_context_position, entry, NULL, NULL, "",
+		MR_print_proc_id_trace_and_context(MR_mdb_out, FALSE,
+			MR_context_position, entry, base_sp, base_curfr, "",
 			filename, lineno, FALSE, "", 0, indent);
 	} else {
 		fflush(MR_mdb_out);
@@ -657,6 +658,55 @@
 			cmd->MR_trace_stop_depth = stop_depth;
 			return STOP_INTERACTING;
 		}
+	} else if (streq(words[0], "fail")) {
+		MR_Determinism	detism = event_info->MR_event_sll->
+					MR_sll_entry->MR_sle_detism;
+		Unsigned	depth = event_info->MR_call_depth;
+		int		stop_depth;
+		int		n;
+
+		cmd->MR_trace_strict = TRUE;
+		cmd->MR_trace_print_level = MR_default_print_level;
+		if (! MR_trace_options_strict_print(cmd, &words, &word_count,
+				"forward", "fail"))
+		{
+			; /* the usage message has already been printed */
+			return KEEP_INTERACTING;
+		} else if (word_count == 2 && MR_trace_is_number(words[1], &n))
+		{
+			stop_depth = depth - n;
+		} else if (word_count == 1) {
+			stop_depth = depth;
+		} else {
+			MR_trace_usage("forward", "fail");
+			return KEEP_INTERACTING;
+		}
+
+		if (MR_DETISM_DET_STACK(detism)) {
+			fflush(MR_mdb_out);
+			fprintf(MR_mdb_err,
+				"mdb: cannot continue until failure: "
+				"selected procedure has determinism %s.\n",
+				MR_detism_names[detism]);
+			return KEEP_INTERACTING;
+		}
+
+		if (depth == stop_depth &&
+			event_info->MR_trace_port == MR_PORT_FAIL)
+		{
+			MR_trace_do_noop();
+		} else if (depth == stop_depth &&
+			event_info->MR_trace_port == MR_PORT_EXCEPTION)
+		{
+			fflush(MR_mdb_out);
+			fprintf(MR_mdb_err,
+				"mdb: cannot continue until failure: "
+				"the call has raised an exception.\n");
+		} else {
+			cmd->MR_trace_cmd = MR_CMD_FAIL;
+			cmd->MR_trace_stop_depth = stop_depth;
+			return STOP_INTERACTING;
+		}
 	} else if (streq(words[0], "exception")) {
 		cmd->MR_trace_strict = TRUE;
 		cmd->MR_trace_print_level = MR_default_print_level;
@@ -777,46 +827,67 @@
 		}
 	} else if (streq(words[0], "retry")) {
 		int		n;
-		int		stop_depth;
-		const char   	*message;
-		Unsigned	depth = event_info->MR_call_depth;
-		MR_Trace_Port	port = event_info->MR_trace_port;
+		int		ancestor_level;
+		const char	*problem;
+		MR_Retry_Result	result;
 
 		if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
-			stop_depth = depth - n;
+			ancestor_level = n;
 		} else if (word_count == 1) {
-			stop_depth = depth;
+			ancestor_level = 0;
 		} else {
 			MR_trace_usage("backward", "retry");
 			return KEEP_INTERACTING;
 		}
 
-		if (stop_depth == depth && MR_port_is_final(port)) {
-			message = MR_trace_retry(event_info, event_details,
-					jumpaddr);
-			if (message != NULL) {
-				fflush(MR_mdb_out);
-				fprintf(MR_mdb_err, "%s\n", message);
-				return KEEP_INTERACTING;
-			}
+		if (ancestor_level == 0 &&
+				MR_port_is_entry(event_info->MR_trace_port))
+		{
+			MR_trace_do_noop();
+			return KEEP_INTERACTING;
+		}
+
+		result = MR_trace_retry(event_info, event_details,
+				ancestor_level, &problem, jumpaddr);
+		switch (result) {
+
+		case MR_RETRY_OK_DIRECT:
 			cmd->MR_trace_cmd = MR_CMD_GOTO;
 			cmd->MR_trace_stop_event = MR_trace_event_number + 1;
 			cmd->MR_trace_strict = FALSE;
 			cmd->MR_trace_print_level = MR_default_print_level;
 			return STOP_INTERACTING;
-		} else if (stop_depth == depth && MR_port_is_entry(port)) {
-			MR_trace_do_noop();
-		} else {
-			/* Finish the call to be retried. */
+
+		case MR_RETRY_OK_FINISH_FIRST:
 			cmd->MR_trace_cmd = MR_CMD_FINISH;
-			cmd->MR_trace_stop_depth = stop_depth;
+			cmd->MR_trace_stop_depth = event_info->MR_call_depth
+							- ancestor_level;
+			cmd->MR_trace_strict = TRUE;
+			cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
+
+			/* Arrange to retry the call once it is finished. */
+			MR_insert_line_at_head("retry");
+			return STOP_INTERACTING;
+
+		case MR_RETRY_OK_FAIL_FIRST:
+			cmd->MR_trace_cmd = MR_CMD_FAIL;
+			cmd->MR_trace_stop_depth = event_info->MR_call_depth
+							- ancestor_level;
 			cmd->MR_trace_strict = TRUE;
 			cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
 
 			/* Arrange to retry the call once it is finished. */
 			MR_insert_line_at_head("retry");
 			return STOP_INTERACTING;
+
+		case MR_RETRY_ERROR:
+			fflush(MR_mdb_out);
+			fprintf(MR_mdb_err, "%s\n", problem);
+			return KEEP_INTERACTING;
 		}
+
+		fatal_error("unrecognized retry result");
+
 	} else if (streq(words[0], "level")) {
 		int	n;
 		bool	detailed;
@@ -1704,16 +1775,17 @@
 #endif
 	} else if (streq(words[0], "stack_regs")) {
 		if (word_count == 1) {
-			MR_print_stack_regs(saved_regs);
+			MR_print_stack_regs(MR_mdb_out, saved_regs);
 		} else {
 			MR_trace_usage("developer", "stack_regs");
 		}
 	} else if (streq(words[0], "all_regs")) {
 		if (word_count == 1) {
-			MR_print_stack_regs(saved_regs);
-			MR_print_heap_regs(saved_regs);
-			MR_print_tabling_regs(saved_regs);
-			MR_print_succip_reg(saved_regs);
+			MR_print_stack_regs(MR_mdb_out, saved_regs);
+			MR_print_heap_regs(MR_mdb_out, saved_regs);
+			MR_print_tabling_regs(MR_mdb_out, saved_regs);
+			MR_print_succip_reg(MR_mdb_out, saved_regs);
+			MR_print_r_regs(MR_mdb_out, saved_regs);
 		} else {
 			MR_trace_usage("developer", "all_regs");
 		}
@@ -1885,57 +1957,6 @@
 	return FALSE;
 }
 
-static void
-MR_print_stack_regs(MR_Word *saved_regs)
-{
-	fprintf(MR_mdb_out, "sp = ");
-	MR_print_detstackptr(MR_mdb_out,
-		MR_saved_sp(saved_regs));
-	fprintf(MR_mdb_out, "\ncurfr = ");
-	MR_print_nondstackptr(MR_mdb_out,
-		MR_saved_curfr(saved_regs));
-	fprintf(MR_mdb_out, "\nmaxfr = ");
-	MR_print_nondstackptr(MR_mdb_out,
-		MR_saved_maxfr(saved_regs));
-	fprintf(MR_mdb_out, "\n");
-}
-
-static void
-MR_print_heap_regs(MR_Word *saved_regs)
-{
-	fprintf(MR_mdb_out, "hp = ");
-	MR_print_heapptr(MR_mdb_out,
-		MR_saved_hp(saved_regs));
-	fprintf(MR_mdb_out, "\nsol_hp = ");
-	MR_print_heapptr(MR_mdb_out,
-		MR_saved_sol_hp(saved_regs));
-	fprintf(MR_mdb_out, "\nmin_hp_rec = ");
-	MR_print_heapptr(MR_mdb_out,
-		MR_saved_min_hp_rec(saved_regs));
-	fprintf(MR_mdb_out, "\nglobal_hp = ");
-	MR_print_heapptr(MR_mdb_out,
-		MR_saved_global_hp(saved_regs));
-	fprintf(MR_mdb_out, "\n");
-}
-
-static void
-MR_print_tabling_regs(MR_Word *saved_regs)
-{
-	fprintf(MR_mdb_out, "gen_next = %ld\n",
-		(long) MR_saved_gen_next(saved_regs));
-	fprintf(MR_mdb_out, "cut_next = %ld\n",
-		(long) MR_saved_cut_next(saved_regs));
-}
-
-static void
-MR_print_succip_reg(MR_Word *saved_regs)
-{
-	fprintf(MR_mdb_out, "succip = ");
-	MR_print_label(MR_mdb_out,
-		MR_saved_gen_next(saved_regs));
-	fprintf(MR_mdb_out, "\n");
-}
-
 static struct MR_option MR_trace_strict_print_opts[] =
 {
 	{ "all",	FALSE,	NULL,	'a' },
@@ -2672,9 +2693,10 @@
 		}
 	}
 
-	MR_print_proc_id_trace_and_context(MR_mdb_out, MR_context_position,
-		event_info->MR_event_sll->MR_sll_entry, NULL, NULL,
-		event_info->MR_event_path, filename, lineno,
+	MR_print_proc_id_trace_and_context(MR_mdb_out, FALSE,
+		MR_context_position, event_info->MR_event_sll->MR_sll_entry,
+		base_sp, base_curfr, event_info->MR_event_path,
+		filename, lineno,
 		MR_port_is_interface(event_info->MR_trace_port),
 		parent_filename, parent_lineno, indent);
 }
Index: trace/mercury_trace_spy.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_spy.c,v
retrieving revision 1.13
diff -u -r1.13 mercury_trace_spy.c
--- trace/mercury_trace_spy.c	2000/09/19 07:14:21	1.13
+++ trace/mercury_trace_spy.c	2000/10/10 00:17:30
@@ -115,8 +115,8 @@
 	** So instead we need to cast the pointers to integers
 	** and compare the integers.
 	*/
-	Unsigned num1 = (Unsigned) address1;
-	Unsigned num2 = (Unsigned) address2;
+	MR_Unsigned num1 = (MR_Unsigned) address1;
+	MR_Unsigned num2 = (MR_Unsigned) address2;
 	return (num1 > num2 ? 1 : num1 == num2 ? 0 : -1);
 }
 
Index: trace/mercury_trace_util.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_util.c,v
retrieving revision 1.1
diff -u -r1.1 mercury_trace_util.c
--- trace/mercury_trace_util.c	2000/07/18 05:53:16	1.1
+++ trace/mercury_trace_util.c	2000/10/10 00:17:30
@@ -1,4 +1,3 @@
-
 /*
 ** Copyright (C) 2000 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
@@ -6,7 +5,8 @@
 */
 
 /*
-** This file contains utility functions for debugger.
+** This file contains utility functions that can be used by any or all
+** of the various kinds of Mercury debuggers.
 **
 ** Author: zs.
 */
@@ -33,4 +33,60 @@
 	}
 
 	return FALSE;
+}
+
+void
+MR_print_stack_regs(FILE *fp, MR_Word *saved_regs)
+{
+	fprintf(fp, "sp = ");
+	MR_print_detstackptr(fp, MR_saved_sp(saved_regs));
+	fprintf(fp, "\ncurfr = ");
+	MR_print_nondstackptr(fp, MR_saved_curfr(saved_regs));
+	fprintf(fp, "\nmaxfr = ");
+	MR_print_nondstackptr(fp, MR_saved_maxfr(saved_regs));
+	fprintf(fp, "\n");
+}
+
+void
+MR_print_heap_regs(FILE *fp, MR_Word *saved_regs)
+{
+	fprintf(fp, "hp = ");
+	MR_print_heapptr(fp, MR_saved_hp(saved_regs));
+	fprintf(fp, "\nsol_hp = ");
+	MR_print_heapptr(fp, MR_saved_sol_hp(saved_regs));
+	fprintf(fp, "\nmin_hp_rec = ");
+	MR_print_heapptr(fp, MR_saved_min_hp_rec(saved_regs));
+	fprintf(fp, "\nglobal_hp = ");
+	MR_print_heapptr(fp, MR_saved_global_hp(saved_regs));
+	fprintf(fp, "\n");
+}
+
+void
+MR_print_tabling_regs(FILE *fp, MR_Word *saved_regs)
+{
+	fprintf(fp, "gen_next = %ld\n", (long) MR_saved_gen_next(saved_regs));
+	fprintf(fp, "cut_next = %ld\n", (long) MR_saved_cut_next(saved_regs));
+}
+
+void
+MR_print_succip_reg(FILE *fp, MR_Word *saved_regs)
+{
+	fprintf(fp, "succip = ");
+	MR_print_label(fp, MR_saved_succip(saved_regs));
+	fprintf(fp, "\n");
+}
+
+void
+MR_print_r_regs(FILE *fp, MR_Word *saved_regs)
+{
+	fprintf(fp, "r1 = %d (%x)\n",
+			MR_saved_r1(saved_regs), MR_saved_r1(saved_regs));
+	fprintf(fp, "r2 = %d (%x)\n",
+			MR_saved_r2(saved_regs), MR_saved_r2(saved_regs));
+	fprintf(fp, "r3 = %d (%x)\n",
+			MR_saved_r3(saved_regs), MR_saved_r3(saved_regs));
+	fprintf(fp, "r4 = %d (%x)\n",
+			MR_saved_r4(saved_regs), MR_saved_r4(saved_regs));
+	fprintf(fp, "r5 = %d (%x)\n",
+			MR_saved_r5(saved_regs), MR_saved_r5(saved_regs));
 }
Index: trace/mercury_trace_util.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_util.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_trace_util.h
--- trace/mercury_trace_util.h	2000/07/18 05:53:16	1.2
+++ trace/mercury_trace_util.h	2000/10/05 02:09:13
@@ -48,4 +48,16 @@
 
 extern	bool	MR_trace_is_number(const char *word, int *value);
 
+/*
+** These functions print the values of sets of Mercury abstract machine
+** registers. Their main use is low level debugging, including debugging
+** the debugger itself.
+*/
+
+extern	void	MR_print_stack_regs(FILE *fp, MR_Word *saved_regs);
+extern	void	MR_print_heap_regs(FILE *fp, MR_Word *saved_regs);
+extern	void	MR_print_tabling_regs(FILE *fp, MR_Word *saved_regs);
+extern	void	MR_print_succip_reg(FILE *fp, MR_Word *saved_regs);
+extern	void	MR_print_r_regs(FILE *fp, MR_Word *saved_regs);
+
 #endif /* MERCURY_TRACE_UTIL_H */
cvs diff: Diffing trax
cvs diff: Diffing trial
cvs diff: Diffing util
--------------------------------------------------------------------------
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