for review: implementation of --no-allow-hijacks

Zoltan Somogyi zs at cs.mu.OZ.AU
Mon Jul 27 19:44:25 AEST 1998


For review by Tyson, since he is the intended beneficiary.

Estimated hours taken: 30

Extend the new failure handling method to optionally preserve an invariant
required by accurate gc: always being able to tell with respect to what MR_sp
or MR_curfr to interpret the stackvars and framevars referred to by the label
whose address is the redoip slot of a nondet stack frame. This basically
requires limitations on the hijacking of redoip/redofr slot pairs.

compiler/notes/failure.html:
	Describe the new extension.

	Change the terminology to conform to what is used in the code.

compiler/llds.m:
	For each temporary frame on the nondet stack, specify the native
	stack of the procedure that created it. This is so that we know
	whether the temporary frame ought to have the fourth slot that
	specifies the right value of MR_sp. (The fourth slot is included
	only in temporary nondet stack frames created procedures that live
	on the det stack; procedures that live on the nondet stack never
	have any of their variables on the det stack.)

	Remove the modframe llds instruction, since it does not specify
	what frame's redoip slot it is assigning to. This is error-prone
	(see peephole.m below). We were not using modframe much anyway.

compiler/llds_out.m:
compiler/opt_debug.m:
	Emit either mktempframe or mkdettempframe depending on the new
	field in temp_frame.

compiler/code_info.m:
	Add a fourth item to the failure state, which states whether
	the top frame of the nondet stack may be hijacked. Initialize
	it from the option --allow-hijacks. If about to do a hijack
	but the failure state says no, create a temporary frame instead.

	Separate out the code for creating temporary frames, since it
	is now called from more than one place. Generalize the code
	to handle the new type of temp frame.

compiler/code_info.m:
compiler/ite_gen.m:
	Simplify the way we transmit information about the location
	of the address of the nondet stack frame in which the soft cut
	is performed from the start of the condition to its end.

compiler/opt_util.m:
	Rename next_modframe as next_assign_to_redoip, and add an additional
	argument that says which frame's redoip are we after.

compiler/peephole.m:
	Use the new argument of opt_util__next_assign_to_redoip to fix a bug
	where a mkframe of a temporary frame (which leaves curfr unchanged)
	that was followed a modframe (which assigns to the redoip of curfr)
	was incorrectly optimized (the assignment to the redoip slot was
	applied to the wrong frame).

compiler/*.m:
	Minor changes to accommodate the disappearance of modframe.

runtime/mercury_stacks.h:
	Add macros to support four-word temp frames on the nondet stack.

	Make the macros that access nondet stack frame slots start with MR_,
	while keeping (redefined) macros needed for backward compatibility.

	Remove the modframe macro.

runtime/mercury_stack_trace.c:
	Modify the stack tracing code to allow for the new four-word temp
	frames.

	Use the new MR_ prefixed variants of the macros.

runtime/mercury_debug.h:
runtime/mercury_misc.[ch]:
	Remove references to modframe.

tests/hard_coded/complex_failure.{m,exp}:
	A new test case to tickle the various ways of handling nested
	disjunctions and if-then-elses in the new code generator.

tests/hard_coded/cycles2.exp:
	Add the missing .exp file for this existing test case.

tests/{general,hard_coded}/space.{m,exp}:
	Move this test case from general to hard_coded. Although NU-Prolog
	can execute it, it does not give the same answers as Mercury due to
	a different default ordering and a difference in integer size (26-bit
	integers in NU-Prolog) that changes the behavior of the pseudo
	random-number generator.

tests/hard_coded/Mmakefile:
	Enable the new test case complex_failure, and the old test cases
	cycles, cycles2 and space, since we now pass them.

tools/bootcheck:
	If the -r option is given, remove the stage2/runtime directory
	before creating it. This fixes a problem we used to have with
	the sequence

		tools/bootcheck .....
		tools/bootcheck -2 -r

	which was that the -2 caused the script to leave the stage2 directory
	in place, including the old (symlinked) stage2/runtime, which meant
	that the -r was in effect ignored (stage2/runtime already had the
	right sources), with potentially incorrect results (since
	stage2/runtime have had object files in the wrong grade
	or compiled with the wrong flags).

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 bytecode/test
cvs diff: Diffing compiler
Index: compiler/basic_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/basic_block.m,v
retrieving revision 1.6
diff -u -u -r1.6 basic_block.m
--- basic_block.m	1998/07/20 10:00:04	1.6
+++ basic_block.m	1998/07/27 07:18:28
@@ -161,7 +161,6 @@
 		Labels = []
 	).
 possible_targets(mkframe(_, _), []).
-possible_targets(modframe(_), []).
 possible_targets(label(_), []).
 possible_targets(goto(CodeAddr), Targets) :-
 	( CodeAddr = label(Label) ->
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.225
diff -u -u -r1.225 code_info.m
--- code_info.m	1998/07/21 14:02:19	1.225
+++ code_info.m	1998/07/26 07:39:11
@@ -275,8 +275,16 @@
 	code_exprn__init_state(ArgList, Varset, StackSlots, FollowVars,
 		Options, ExprnInfo),
 	stack__init(ResumePoints),
+	globals__lookup_bool_option(Globals, allow_hijacks, AllowHijack),
+	(
+		AllowHijack = yes,
+		Hijack = allowed
+	;
+		AllowHijack = no,
+		Hijack = not_allowed
+	),
 	DummyFailInfo = fail_info(ResumePoints, resume_point_unknown,
-		may_be_different),
+		may_be_different, Hijack),
 	set__init(AvailSlots),
 	map__init(TempsInUse),
 	set__init(Zombies),
@@ -754,7 +762,7 @@
 
 code_info__current_resume_point_vars(ResumeVars) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePointStack, _, _) },
+	{ FailInfo = fail_info(ResumePointStack, _, _, _) },
 	{ stack__top_det(ResumePointStack, ResumePointInfo) },
 	{ code_info__pick_first_resume_point(ResumePointInfo, ResumeMap, _) },
 	{ map__keys(ResumeMap, ResumeMapVarList) },
@@ -885,8 +893,8 @@
 			% branched structure with is valid for all branches.
 		code_info__get_fail_info(FailInfo0, EndCodeInfo0, _),
 		code_info__get_fail_info(FailInfo1, EndCodeInfo1, _),
-		FailInfo0 = fail_info(_, ResumeKnown0, CurfrMaxfr0),
-		FailInfo1 = fail_info(R, ResumeKnown1, CurfrMaxfr1),
+		FailInfo0 = fail_info(_, ResumeKnown0, CurfrMaxfr0, Hijack0),
+		FailInfo1 = fail_info(R, ResumeKnown1, CurfrMaxfr1, Hijack1),
 		(
 			ResumeKnown0 = resume_point_known,
 			ResumeKnown1 = resume_point_known
@@ -903,7 +911,15 @@
 		;
 			CurfrMaxfr = may_be_different
 		),
-		FailInfo = fail_info(R, ResumeKnown, CurfrMaxfr),
+		(
+			Hijack0 = allowed,
+			Hijack1 = allowed
+		->
+			Hijack = allowed
+		;
+			Hijack = not_allowed
+		),
+		FailInfo = fail_info(R, ResumeKnown, CurfrMaxfr, Hijack),
 		code_info__set_fail_info(FailInfo, EndCodeInfo1, EndCodeInfo)
 	},
 	{ MaybeEnd = yes(branch_end_info(EndCodeInfo)) }.
@@ -986,14 +1002,6 @@
 	% will then override the redoip slot to point to the start of
 	% the else part before generating the code of the condition.
 	%
-	% However, some conditions will themselves hijack this redoip slot.
-	% If this is the case, `maybe_push_temp_frame' will protect against
-	% this by pushing a temporary nondet frame solely for the purpose
-	% of having its redoip and redofr slots hijacked by the condition.
-	% In any case it returns the lval that `ite_enter_then' should use to
-	% refer to the stack frame containing the redoip slot that was
-	% overridden for the if-then-else.
-	%
 	% `ite_enter_then', which should be called generating code for
 	% the condition, sets up the failure state of the code generator
 	% for generating the then-part, and returns the code sequences
@@ -1005,12 +1013,8 @@
 :- pred code_info__prepare_for_ite_hijack(code_model::in,
 	ite_hijack_info::out, code_tree::out,
 	code_info::in, code_info::out) is det.
-
-:- pred code_info__maybe_push_temp_frame(code_model::in, bool::in,
-	ite_hijack_info::in, lval::out, code_tree::out,
-	code_info::in, code_info::out) is det.
 
-:- pred code_info__ite_enter_then(ite_hijack_info::in, lval::in,
+:- pred code_info__ite_enter_then(ite_hijack_info::in,
 	code_tree::out, code_tree::out, code_info::in, code_info::out) is det.
 
 	% `enter_simple_neg' and `leave_simple_neg' should be called before
@@ -1158,7 +1162,8 @@
 	--->	fail_info(
 			stack(resume_point_info),
 			resume_point_known,
-			curfr_vs_maxfr
+			curfr_vs_maxfr,
+			hijack_allowed
 		).
 
 	% A resumption point has one or two labels associated with it.
@@ -1190,10 +1195,14 @@
 :- type curfr_vs_maxfr		--->	must_be_equal
 				;	may_be_different.
 
+:- type hijack_allowed		--->	allowed
+				;	not_allowed.
+
 %---------------------------------------------------------------------------%
 
 :- type disj_hijack_info
 	--->	disj_no_hijack
+	;	disj_temp_frame
 	;	disj_quarter_hijack
 	;	disj_half_hijack(
 			lval		% The stack slot in which we saved
@@ -1207,70 +1216,70 @@
 		).
 
 code_info__prepare_for_disj_hijack(CodeModel, HijackInfo, Code) -->
-	( { CodeModel = model_non } ->
-		code_info__get_fail_info(FailInfo),
-		{ FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr) },
-		(
-			{ CurfrMaxfr = may_be_different },
-			code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
-				RedoipSlot),
-			code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
-				RedofrSlot),
-			{ HijackInfo = disj_full_hijack(RedoipSlot,
-				RedofrSlot) },
-			{ Code = node([
-				assign(RedoipSlot, lval(redoip(lval(maxfr))))
-					- "prepare for full disj hijack",
-				assign(RedofrSlot, lval(redofr(lval(maxfr))))
-					- "prepare for full disj hijack",
-				assign(redofr(lval(maxfr)), lval(curfr))
-					- "prepare for full disj hijack"
-			]) }
-		;
-			{ CurfrMaxfr = must_be_equal },
-			(
-				{ ResumeKnown = resume_point_unknown },
-				code_info__acquire_temp_slot(
-					lval(redoip(lval(curfr))), RedoipSlot),
-				{ HijackInfo = disj_half_hijack(RedoipSlot) },
-				{ Code = node([
-					assign(RedoipSlot,
-						lval(redoip(lval(curfr))))
-						- "prepare for half disj hijack"
-				]) }
-			;
-				{ ResumeKnown = resume_point_known },
-				{ HijackInfo = disj_quarter_hijack },
-				{ Code = empty }
-			)
-		)
-	;
+	code_info__get_fail_info(FailInfo),
+	{ FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr, Allow) },
+	(
+		{ CodeModel \= model_non }
+	->
 		{ HijackInfo = disj_no_hijack },
-		{ Code = empty }
+		{ Code = node([
+			comment("disj no hijack")
+				- ""
+		]) }
+	;
+		{ Allow = not_allowed }
+	->
+		{ HijackInfo = disj_temp_frame },
+		code_info__create_temp_frame(do_fail,
+			"prepare for disjunction", Code)
+	;
+		{ CurfrMaxfr = must_be_equal },
+		{ ResumeKnown = resume_point_known }
+	->
+		{ HijackInfo = disj_quarter_hijack },
+		{ Code = node([
+			comment("disj quarter hijack")
+				- ""
+		]) }
+	;
+		{ CurfrMaxfr = must_be_equal }
+	->
+		% { ResumeKnown = resume_point_unknown },
+		code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
+			RedoipSlot),
+		{ HijackInfo = disj_half_hijack(RedoipSlot) },
+		{ Code = node([
+			assign(RedoipSlot, lval(redoip(lval(curfr))))
+				- "prepare for half disj hijack"
+		]) }
+	;
+		% { CurfrMaxfr = may_be_different },
+		code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
+			RedoipSlot),
+		code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
+			RedofrSlot),
+		{ HijackInfo = disj_full_hijack(RedoipSlot, RedofrSlot) },
+		{ Code = node([
+			assign(RedoipSlot, lval(redoip(lval(maxfr))))
+				- "prepare for full disj hijack",
+			assign(RedofrSlot, lval(redofr(lval(maxfr))))
+				- "prepare for full disj hijack",
+			assign(redofr(lval(maxfr)), lval(curfr))
+				- "prepare for full disj hijack"
+		]) }
 	).
 
 code_info__undo_disj_hijack(HijackInfo, Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr, _) },
 	(
-		{ HijackInfo = disj_full_hijack(RedoipSlot, RedofrSlot) },
-		{ require(unify(CurfrMaxfr, may_be_different),
-			"maxfr same as curfr in disj_full_hijack") },
-		{ Code = node([
-			assign(redoip(lval(maxfr)), lval(RedoipSlot))
-				- "restore redoip for full disj hijack",
-			assign(redofr(lval(maxfr)), lval(RedofrSlot))
-				- "restore redofr for full disj hijack"
-		]) }
+		{ HijackInfo = disj_no_hijack },
+		{ Code = empty }
 	;
-		{ HijackInfo = disj_half_hijack(RedoipSlot) },
-		{ require(unify(ResumeKnown, resume_point_unknown),
-			"resume point known in disj_half_hijack") },
-		{ require(unify(CurfrMaxfr, must_be_equal),
-			"maxfr may differ from curfr in disj_half_hijack") },
+		{ HijackInfo = disj_temp_frame },
 		{ Code = node([
-			assign(redoip(lval(curfr)), lval(RedoipSlot))
-				- "restore redoip for half disj hijack"
+			assign(maxfr, lval(prevfr(lval(maxfr))))
+				- "restore maxfr for temp frame disj"
 		]) }
 	;
 		{ HijackInfo = disj_quarter_hijack },
@@ -1287,26 +1296,48 @@
 				- "restore redoip for quarter disj hijack"
 		]) }
 	;
-		{ HijackInfo = disj_no_hijack },
-		{ Code = empty }
+		{ HijackInfo = disj_half_hijack(RedoipSlot) },
+		{ require(unify(ResumeKnown, resume_point_unknown),
+			"resume point known in disj_half_hijack") },
+		{ require(unify(CurfrMaxfr, must_be_equal),
+			"maxfr may differ from curfr in disj_half_hijack") },
+		{ Code = node([
+			assign(redoip(lval(curfr)), lval(RedoipSlot))
+				- "restore redoip for half disj hijack"
+		]) }
+	;
+		{ HijackInfo = disj_full_hijack(RedoipSlot, RedofrSlot) },
+		{ require(unify(CurfrMaxfr, may_be_different),
+			"maxfr same as curfr in disj_full_hijack") },
+		{ Code = node([
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for full disj hijack",
+			assign(redofr(lval(maxfr)), lval(RedofrSlot))
+				- "restore redofr for full disj hijack"
+		]) }
 	).
 
 %---------------------------------------------------------------------------%
 
 :- type ite_hijack_info
-	--->	ite_no_hijack(
-			resume_point_known
-		)
-	;	ite_quarter_hijack(
-			resume_point_known
+	--->	ite_info(
+			resume_point_known,
+			hijack_allowed,
+			ite_hijack_type
+		).
+
+:- type ite_hijack_type
+	--->	ite_no_hijack
+	;	ite_temp_frame(
+			lval		% The stack slot in which we saved
+					% the value of maxfr.
 		)
+	;	ite_quarter_hijack
 	;	ite_half_hijack(
-			resume_point_known,
 			lval		% The stack slot in which we saved
 					% the value of the hijacked redoip.
 		)
 	;	ite_full_hijack(
-			resume_point_known,
 			lval,		% The stack slot in which we saved
 					% the value of the hijacked redoip.
 			lval,		% The stack slot in which we saved
@@ -1316,111 +1347,96 @@
 		).
 
 code_info__prepare_for_ite_hijack(EffCodeModel, HijackInfo, Code) -->
-	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(_ResumePoints, ResumeKnown, CurfrMaxfr) },
-	( { EffCodeModel = model_non } ->
-		(
-			{ CurfrMaxfr = may_be_different },
-			code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
-				RedoipSlot),
-			code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
-				RedofrSlot),
-			code_info__acquire_temp_slot(lval(maxfr),
-				MaxfrSlot),
-			{ HijackInfo = ite_full_hijack(ResumeKnown,
-				RedoipSlot, RedofrSlot, MaxfrSlot) },
-			{ Code = node([
-				assign(MaxfrSlot, lval(maxfr))
-					- "prepare for full ite hijack",
-				assign(RedoipSlot, lval(redoip(lval(maxfr))))
-					- "prepare for full ite hijack",
-				assign(RedofrSlot, lval(redofr(lval(maxfr))))
-					- "prepare for full ite hijack",
-				assign(redofr(lval(maxfr)), lval(curfr))
-					- "prepare for full ite hijack"
-			]) }
-		;
-			{ CurfrMaxfr = must_be_equal },
-			(
-				{ ResumeKnown = resume_point_unknown },
-				code_info__acquire_temp_slot(
-					lval(redoip(lval(curfr))), RedoipSlot),
-				{ HijackInfo = ite_half_hijack(ResumeKnown,
-					RedoipSlot) },
-				{ Code = node([
-					assign(RedoipSlot,
-						lval(redoip(lval(curfr))))
-						- "prepare for half ite hijack"
-				]) }
-			;
-				{ ResumeKnown = resume_point_known },
-				{ HijackInfo = ite_quarter_hijack(
-					ResumeKnown) },
-				{ Code = empty }
-			)
-		)
+	code_info__get_fail_info(FailInfo),
+	{ FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr, Allow) },
+	(
+		{ EffCodeModel \= model_non }
+	->
+		{ HijackType = ite_no_hijack },
+		{ Code = node([
+			comment("ite no hijack")
+				- ""
+		]) }
 	;
-		{ HijackInfo = ite_no_hijack(ResumeKnown) },
-		{ Code = empty }
-	).
-
-code_info__maybe_push_temp_frame(EffCodeModel, CanHijack, HijackInfo,
-		CutFrame, Code) -->
-	( { EffCodeModel = model_non } ->
-		( { HijackInfo = ite_full_hijack(_, _, _, MaxfrSlot0) } ->
-			{ CutFrame = MaxfrSlot0 }
-		;
-			{ CutFrame = curfr }
-		),
-		(
-			{ CanHijack = yes },
-			{ Code = node([
-				mkframe(temp_frame, do_fail)
-					- "protect slots hijacked by ite"
-			]) },
-			code_info__get_fail_info(FailInfo0),
-			{ FailInfo0 = fail_info(ResumePoints, ResumeKnown,
-				_) },
-			{ FailInfo = fail_info(ResumePoints, ResumeKnown,
-				may_be_different) },
-			code_info__set_fail_info(FailInfo)
-		;
-			{ CanHijack = no },
-			{ Code = empty }
-		)
+		{ Allow = not_allowed }
+	->
+		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
+		{ HijackType = ite_temp_frame(MaxfrSlot) },
+		code_info__create_temp_frame(do_fail, "prepare for ite",
+			TempFrameCode),
+		{ MaxfrCode = node([
+			assign(MaxfrSlot, lval(maxfr))
+				- "prepare for ite"
+		]) },
+		{ Code = tree(TempFrameCode, MaxfrCode) }
 	;
-		{ CutFrame = maxfr },
-		{ Code = empty }
-	).
+		{ CurfrMaxfr = must_be_equal },
+		{ ResumeKnown = resume_point_known }
+	->
+		{ HijackType = ite_quarter_hijack },
+		{ Code = node([
+			comment("ite quarter hijack")
+				- ""
+		]) }
+	;
+		{ CurfrMaxfr = must_be_equal }
+	->
+		% { ResumeKnown = resume_point_unknown },
+		code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
+			RedoipSlot),
+		{ HijackType = ite_half_hijack(RedoipSlot) },
+		{ Code = node([
+			assign(RedoipSlot, lval(redoip(lval(curfr))))
+				- "prepare for half ite hijack"
+		]) }
+	;
+		% { CurfrMaxfr = may_be_different },
+		code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
+			RedoipSlot),
+		code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
+			RedofrSlot),
+		code_info__acquire_temp_slot(lval(maxfr),
+			MaxfrSlot),
+		{ HijackType = ite_full_hijack(RedoipSlot, RedofrSlot,
+			MaxfrSlot) },
+		{ Code = node([
+			assign(MaxfrSlot, lval(maxfr))
+				- "prepare for full ite hijack",
+			assign(RedoipSlot, lval(redoip(lval(maxfr))))
+				- "prepare for full ite hijack",
+			assign(RedofrSlot, lval(redofr(lval(maxfr))))
+				- "prepare for full ite hijack",
+			assign(redofr(lval(maxfr)), lval(curfr))
+				- "prepare for full ite hijack"
+		]) }
+	),
+	{ HijackInfo = ite_info(ResumeKnown, Allow, HijackType) },
+	code_info__disallow_hijack.
 
-code_info__ite_enter_then(HijackInfo, CutFrame, ThenCode, ElseCode) -->
+code_info__ite_enter_then(HijackInfo, ThenCode, ElseCode) -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints0, ResumeKnown0, CurfrMaxfr) },
+	{ FailInfo0 = fail_info(ResumePoints0, ResumeKnown0, CurfrMaxfr,
+		_) },
 	{ stack__pop_det(ResumePoints0, _, ResumePoints) },
+	{ HijackInfo = ite_info(ResumeKnown1, Allow1, HijackType) },
 	{
-		HijackInfo = ite_full_hijack(ResumeKnown1,
-			RedoipSlot, RedofrSlot, MaxfrSlot),
+		HijackType = ite_no_hijack,
+		ThenCode = empty,
+		ElseCode = ThenCode
+	;
+		HijackType = ite_temp_frame(MaxfrSlot),
 		ThenCode = node([
-			assign(redoip(lval(MaxfrSlot)), lval(RedoipSlot))
-				- "restore redoip for full ite hijack",
-			assign(redofr(lval(MaxfrSlot)), lval(RedofrSlot))
-				- "restore redofr for full ite hijack"
+			% We can't remove the frame, it may not be on top.
+			assign(redoip(lval(MaxfrSlot)),
+				const(code_addr_const(do_fail)))
+				- "soft cut for temp frame ite"
 		]),
 		ElseCode = node([
-			assign(redoip(lval(maxfr)), lval(RedoipSlot))
-				- "restore redoip for full ite hijack",
-			assign(redofr(lval(maxfr)), lval(RedofrSlot))
-				- "restore redofr for full ite hijack"
+			assign(maxfr, lval(prevfr(lval(MaxfrSlot))))
+				- "restore maxfr for temp frame ite"
 		])
 	;
-		HijackInfo = ite_half_hijack(ResumeKnown1, RedoipSlot),
-		ThenCode = node([
-			assign(redoip(lval(CutFrame)), lval(RedoipSlot))
-				- "restore redoip for half ite hijack"
-		]),
-		ElseCode = ThenCode
-	;
-		HijackInfo = ite_quarter_hijack(ResumeKnown1),
+		HijackType = ite_quarter_hijack,
 		stack__top_det(ResumePoints, ResumePoint),
 		(
 			code_info__maybe_pick_stack_resume_point(ResumePoint,
@@ -1428,17 +1444,37 @@
 		->
 			LabelConst = const(code_addr_const(StackLabel)),
 			ThenCode = node([
-				assign(redoip(lval(CutFrame)), LabelConst) -
+				assign(redoip(lval(curfr)), LabelConst) -
 					"restore redoip for quarter ite hijack"
 			])
 		;
+			% This can happen only if ResumePoint is unreachable
+			% from here.
 			ThenCode = empty
 		),
 		ElseCode = ThenCode
 	;
-		HijackInfo = ite_no_hijack(ResumeKnown1),
-		ThenCode = empty,
+		HijackType = ite_half_hijack(RedoipSlot),
+		ThenCode = node([
+			assign(redoip(lval(curfr)), lval(RedoipSlot))
+				- "restore redoip for half ite hijack"
+		]),
 		ElseCode = ThenCode
+	;
+		HijackType = ite_full_hijack(RedoipSlot, RedofrSlot,
+			MaxfrSlot),
+		ThenCode = node([
+			assign(redoip(lval(MaxfrSlot)), lval(RedoipSlot))
+				- "restore redoip for full ite hijack",
+			assign(redofr(lval(MaxfrSlot)), lval(RedofrSlot))
+				- "restore redofr for full ite hijack"
+		]),
+		ElseCode = node([
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for full ite hijack",
+			assign(redofr(lval(maxfr)), lval(RedofrSlot))
+				- "restore redofr for full ite hijack"
+		])
 	},
 	{
 		ResumeKnown0 = resume_point_known,
@@ -1448,7 +1484,8 @@
 	;
 		ResumeKnown = resume_point_unknown
 	},
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr,
+		Allow1) },
 	code_info__set_fail_info(FailInfo).
 
 %---------------------------------------------------------------------------%
@@ -1500,7 +1537,7 @@
 
 code_info__prepare_for_det_commit(DetCommitInfo, Code) -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(_, _, CurfrMaxfr) },
+	{ FailInfo0 = fail_info(_, _, CurfrMaxfr, _) },
 	(
 		{ CurfrMaxfr = may_be_different },
 		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
@@ -1550,7 +1587,11 @@
 		).
 
 :- type commit_hijack_info
-	--->	commit_quarter_hijack
+	--->	commit_temp_frame(
+			lval		% The stack slot in which we saved
+					% the old value of maxfr.
+		)
+	;	commit_quarter_hijack
 	;	commit_half_hijack(
 			lval		% The stack slot in which we saved
 					% the value of the hijacked redoip.
@@ -1566,23 +1607,57 @@
 
 code_info__prepare_for_semi_commit(SemiCommitInfo, Code) -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints0, ResumeKnown, CurfrMaxfr) },
+	{ FailInfo0 = fail_info(ResumePoints0, ResumeKnown, CurfrMaxfr,
+		Allow) },
 	{ stack__top_det(ResumePoints0, TopResumePoint) },
 	code_info__clone_resume_point(TopResumePoint, NewResumePoint),
 	{ stack__push(ResumePoints0, NewResumePoint, ResumePoints) },
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr, Allow) },
 	code_info__set_fail_info(FailInfo),
 
 	{ code_info__pick_stack_resume_point(NewResumePoint, _, StackLabel) },
 	{ StackLabelConst = const(code_addr_const(StackLabel)) },
 	(
-		{ CurfrMaxfr = may_be_different },
+		{ Allow = not_allowed }
+	->
+		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
+		{ HijackInfo = commit_temp_frame(MaxfrSlot) },
+		{ MaxfrCode = node([
+			assign(MaxfrSlot, lval(maxfr))
+				- "prepare for temp frame commit"
+		]) },
+		code_info__create_temp_frame(StackLabel,
+			"prepare for temp frame commit", TempFrameCode),
+		{ HijackCode = tree(MaxfrCode, TempFrameCode) }
+	;
+		{ ResumeKnown = resume_point_known },
+		{ CurfrMaxfr = must_be_equal }
+	->
+		{ HijackInfo = commit_quarter_hijack },
+		{ HijackCode = node([
+			assign(redoip(lval(curfr)), StackLabelConst)
+				- "hijack the redofr slot"
+		]) }
+	;
+		{ CurfrMaxfr = must_be_equal }
+	->
+		% { ResumeKnown = resume_point_unknown }
+		code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
+			RedoipSlot),
+		{ HijackInfo = commit_half_hijack(RedoipSlot) },
+		{ HijackCode = node([
+			assign(RedoipSlot, lval(redoip(lval(curfr))))
+				- "prepare for half commit hijack",
+			assign(redoip(lval(curfr)), StackLabelConst)
+				- "hijack the redofr slot"
+		]) }
+	;
+		% { CurfrMaxfr = may_be_different }
 		code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
 			RedoipSlot),
 		code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
 			RedofrSlot),
-		code_info__acquire_temp_slot(lval(maxfr),
-			MaxfrSlot),
+		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
 		{ HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot,
 			MaxfrSlot) },
 		{ HijackCode = node([
@@ -1597,27 +1672,6 @@
 			assign(redoip(lval(maxfr)), StackLabelConst)
 				- "hijack the redoip slot"
 		]) }
-	;
-		{ CurfrMaxfr = must_be_equal },
-		(
-			{ ResumeKnown = resume_point_unknown },
-			code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
-				RedoipSlot),
-			{ HijackInfo = commit_half_hijack(RedoipSlot) },
-			{ HijackCode = node([
-				assign(RedoipSlot, lval(redoip(lval(curfr))))
-					- "prepare for half commit hijack",
-				assign(redoip(lval(curfr)), StackLabelConst)
-					- "hijack the redofr slot"
-			]) }
-		;
-			{ ResumeKnown = resume_point_known },
-			{ HijackInfo = commit_quarter_hijack },
-			{ HijackCode = node([
-				assign(redoip(lval(curfr)), StackLabelConst)
-					- "hijack the redofr slot"
-			]) }
-		)
 	),
 	code_info__maybe_save_trail_info(MaybeTrailSlots, SaveTrailCode),
 	{ SemiCommitInfo = semi_commit_info(FailInfo0, NewResumePoint,
@@ -1630,21 +1684,28 @@
 
 	code_info__set_fail_info(FailInfo),
 	(
-		{ HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot,
-			MaxfrSlot) },
+		{ HijackInfo = commit_temp_frame(MaxfrSlot) },
 		{ SuccessUndoCode = node([
 			assign(maxfr, lval(MaxfrSlot))
-				- "restore maxfr for full commit hijack",
-			assign(redoip(lval(maxfr)), lval(RedoipSlot))
-				- "restore redoip for full commit hijack",
-			assign(redofr(lval(maxfr)), lval(RedofrSlot))
-				- "restore redofr for full commit hijack"
+				- "restore maxfr for full commit hijack"
 		]) },
+		{ FailureUndoCode = SuccessUndoCode }
+	;
+		{ HijackInfo = commit_quarter_hijack },
+		{ FailInfo = fail_info(ResumePoints, _, _, _) },
+		{ stack__top_det(ResumePoints, TopResumePoint) },
+		{ code_info__pick_stack_resume_point(TopResumePoint,
+			_, StackLabel) },
+		{ StackLabelConst = const(code_addr_const(StackLabel)) },
+		{ SuccessUndoCode = node([
+			assign(maxfr, lval(curfr))
+				- "restore maxfr for quarter commit hijack",
+			assign(redoip(lval(maxfr)), StackLabelConst)
+				- "restore redoip for quarter commit hijack"
+		]) },
 		{ FailureUndoCode = node([
-			assign(redoip(lval(maxfr)), lval(RedoipSlot))
-				- "restore redoip for full commit hijack",
-			assign(redofr(lval(maxfr)), lval(RedofrSlot))
-				- "restore redofr for full commit hijack"
+			assign(redoip(lval(maxfr)), StackLabelConst)
+				- "restore redoip for quarter commit hijack"
 		]) }
 	;
 		{ HijackInfo = commit_half_hijack(RedoipSlot) },
@@ -1659,21 +1720,21 @@
 				- "restore redoip for half commit hijack"
 		]) }
 	;
-		{ HijackInfo = commit_quarter_hijack },
-		{ FailInfo = fail_info(ResumePoints, _, _) },
-		{ stack__top_det(ResumePoints, TopResumePoint) },
-		{ code_info__pick_stack_resume_point(TopResumePoint,
-			_, StackLabel) },
-		{ StackLabelConst = const(code_addr_const(StackLabel)) },
+		{ HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot,
+			MaxfrSlot) },
 		{ SuccessUndoCode = node([
-			assign(maxfr, lval(curfr))
-				- "restore maxfr for quarter commit hijack",
-			assign(redoip(lval(maxfr)), StackLabelConst)
-				- "restore redoip for quarter commit hijack"
+			assign(maxfr, lval(MaxfrSlot))
+				- "restore maxfr for full commit hijack",
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for full commit hijack",
+			assign(redofr(lval(maxfr)), lval(RedofrSlot))
+				- "restore redofr for full commit hijack"
 		]) },
 		{ FailureUndoCode = node([
-			assign(redoip(lval(maxfr)), StackLabelConst)
-				- "restore redoip for quarter commit hijack"
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for full commit hijack",
+			assign(redofr(lval(maxfr)), lval(RedofrSlot))
+				- "restore redofr for full commit hijack"
 		]) }
 	),
 
@@ -1711,9 +1772,41 @@
 
 %---------------------------------------------------------------------------%
 
+:- pred code_info__disallow_hijack(code_info::in, code_info::out) is det.
+
+code_info__disallow_hijack -->
+	code_info__get_fail_info(FailInfo0),
+	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr, _) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr,
+		not_allowed) },
+	code_info__set_fail_info(FailInfo).
+
+:- pred code_info__create_temp_frame(code_addr::in, string::in, code_tree::out,
+	code_info::in, code_info::out) is det.
+
+code_info__create_temp_frame(Redoip, Comment, Code) -->
+	code_info__get_proc_model(ProcModel),
+	{ ProcModel = model_non ->
+		Kind = nondet_stack_proc
+	;
+		Kind = det_stack_proc
+	},
+	{ Code = node([
+		mkframe(temp_frame(Kind), Redoip)
+			- Comment
+	]) },
+	code_info__get_fail_info(FailInfo0),
+	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, _, Allow) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, may_be_different,
+		Allow) },
+	code_info__set_fail_info(FailInfo).
+
+%---------------------------------------------------------------------------%
+
 code_info__effect_resume_point(ResumePoint, CodeModel, Code) -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints0, _ResumeKnown, CurfrMaxfr) },
+	{ FailInfo0 = fail_info(ResumePoints0, _ResumeKnown, CurfrMaxfr,
+		Allow) },
 
 	{ stack__top(ResumePoints0, OldResumePoint) ->
 		code_info__pick_first_resume_point(OldResumePoint, OldMap, _),
@@ -1729,7 +1822,8 @@
 	},
 
 	{ stack__push(ResumePoints0, ResumePoint, ResumePoints) },
-	{ FailInfo = fail_info(ResumePoints, resume_point_known, CurfrMaxfr) },
+	{ FailInfo = fail_info(ResumePoints, resume_point_known, CurfrMaxfr,
+		Allow) },
 	code_info__set_fail_info(FailInfo),
 	( { CodeModel = model_non } ->
 		{ code_info__pick_stack_resume_point(ResumePoint,
@@ -1747,28 +1841,28 @@
 
 code_info__top_resume_point(ResumePoint) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, _, _) },
+	{ FailInfo = fail_info(ResumePoints, _, _, _) },
 	{ stack__top_det(ResumePoints, ResumePoint) }.
 
 code_info__set_resume_point_to_unknown -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints, _, CurfrMaxfr) },
+	{ FailInfo0 = fail_info(ResumePoints, _, CurfrMaxfr, Allow) },
 	{ FailInfo = fail_info(ResumePoints, resume_point_unknown,
-		CurfrMaxfr) },
+		CurfrMaxfr, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 code_info__set_resume_point_and_frame_to_unknown -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints, _, _) },
+	{ FailInfo0 = fail_info(ResumePoints, _, _, Allow) },
 	{ FailInfo = fail_info(ResumePoints, resume_point_unknown,
-		may_be_different) },
+		may_be_different, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 %---------------------------------------------------------------------------%
 
 code_info__generate_failure(Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _) },
 	(
 		{ ResumeKnown = resume_point_known },
 		{ stack__top_det(ResumePoints, TopResumePoint) },
@@ -1795,7 +1889,7 @@
 
 code_info__fail_if_rval_is_false(Rval0, Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _) },
 	(
 		{ ResumeKnown = resume_point_known },
 		{ stack__top_det(ResumePoints, TopResumePoint) },
@@ -1849,13 +1943,13 @@
 
 code_info__failure_is_direct_branch(CodeAddr) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, resume_point_known, _) },
+	{ FailInfo = fail_info(ResumePoints, resume_point_known, _, _) },
 	{ stack__top(ResumePoints, TopResumePoint) },
 	code_info__pick_matching_resume_addr(TopResumePoint, CodeAddr).
 
 code_info__may_use_nondet_tailcall(MayTailCall) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _) },
 	(
 		{ ResumeKnown = resume_point_known },
 		{ stack__top_det(ResumePoints, TopResumePoint) },
@@ -1975,7 +2069,7 @@
 
 code_info__flush_resume_vars_to_stack(Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePointStack, _, _) },
+	{ FailInfo = fail_info(ResumePointStack, _, _, _) },
 	{ stack__top_det(ResumePointStack, ResumePoint) },
 	{ code_info__pick_stack_resume_point(ResumePoint, StackMap, _) },
 	{ map__to_assoc_list(StackMap, StackLocs) },
@@ -2024,7 +2118,9 @@
 	{ ResumePoint = stack_only(StackMap, ResumeAddress) },
 	{ stack__init(ResumeStack0) },
 	{ stack__push(ResumeStack0, ResumePoint, ResumeStack) },
-	{ FailInfo = fail_info(ResumeStack, ResumeKnown, CurfrMaxfr) },
+	code_info__get_fail_info(FailInfo0),
+	{ FailInfo0 = fail_info(_, _, _, Allow) },
+	{ FailInfo = fail_info(ResumeStack, ResumeKnown, CurfrMaxfr, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 %---------------------------------------------------------------------------%
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.34
diff -u -u -r1.34 dupelim.m
--- dupelim.m	1998/07/20 10:00:39	1.34
+++ dupelim.m	1998/07/27 07:06:37
@@ -297,9 +297,6 @@
 		Instr1 = mkframe(_, _),
 		Instr = Instr1
 	;
-		Instr1 = modframe(_),
-		Instr = Instr1
-	;
 		Instr1 = label(_),
 		Instr = Instr1
 	;
@@ -569,10 +566,6 @@
 		Instr2 = Instr1,
 		Instr = Instr1
 	;
-		Instr1 = modframe(_),
-		Instr2 = Instr1,
-		Instr = Instr1
-	;
 		Instr1 = label(_),
 		Instr2 = Instr1,
 		Instr = Instr1
@@ -802,8 +795,6 @@
 	dupelim__replace_labels_code_addr(Return0, ReplMap, Return).
 dupelim__replace_labels_instr(mkframe(NondetFrameInfo, Redoip0), ReplMap,
 		mkframe(NondetFrameInfo, Redoip)) :-
-	dupelim__replace_labels_code_addr(Redoip0, ReplMap, Redoip).
-dupelim__replace_labels_instr(modframe(Redoip0), ReplMap, modframe(Redoip)) :-
 	dupelim__replace_labels_code_addr(Redoip0, ReplMap, Redoip).
 dupelim__replace_labels_instr(label(Label), ReplMap, label(Label)) :-
 	( map__search(ReplMap, Label, _) ->
Index: compiler/frameopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/frameopt.m,v
retrieving revision 1.71
diff -u -u -r1.71 frameopt.m
--- frameopt.m	1998/07/20 10:00:43	1.71
+++ frameopt.m	1998/07/27 07:06:02
@@ -667,7 +667,6 @@
 		Labels = []
 	).
 possible_targets(mkframe(_, _), []).
-possible_targets(modframe(_), []).
 possible_targets(label(_), []).
 possible_targets(goto(CodeAddr), Targets) :-
 	( CodeAddr = label(Label) ->
@@ -1276,7 +1275,6 @@
 	).
 substitute_labels_instr(mkframe(NondetFrameInfo, Redoip), _,
 		mkframe(NondetFrameInfo, Redoip)).
-substitute_labels_instr(modframe(Redoip), _, modframe(Redoip)).
 substitute_labels_instr(label(_), _, _) :-
 	error("label in substitute_labels_instr").
 substitute_labels_instr(goto(CodeAddr0), LabelMap, goto(CodeAddr)) :-
Index: compiler/ite_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ite_gen.m,v
retrieving revision 1.57
diff -u -u -r1.57 ite_gen.m
--- ite_gen.m	1998/07/22 19:28:50	1.57
+++ ite_gen.m	1998/07/24 10:38:51
@@ -99,15 +99,10 @@
 	code_info__effect_resume_point(ResumePoint, EffCodeModel,
 		EffectResumeCode),
 
-	{ goal_may_hijack_top_redoip(CondGoal, CondMayHijack) },
-	code_info__maybe_push_temp_frame(EffCodeModel, CondMayHijack,
-		HijackInfo, CurFrameLval, TempFrameCode),
-
 		% Generate the condition
 	code_gen__generate_goal(CondCodeModel, CondGoal, CondCode),
 
-	code_info__ite_enter_then(HijackInfo, CurFrameLval,
-		ThenNeckCode, ElseNeckCode),
+	code_info__ite_enter_then(HijackInfo, ThenNeckCode, ElseNeckCode),
 
 		% Kill again any variables that have become zombies
 	code_info__pickup_zombies(Zombies),
@@ -168,7 +163,6 @@
 		tree(SaveTicketCode,
 		tree(PrepareHijackCode,
 		tree(EffectResumeCode,
-		tree(TempFrameCode,
 		tree(CondCode,
 		tree(ThenNeckCode,
 		tree(DiscardTicketCode,
@@ -183,7 +177,7 @@
 		tree(ElseTraceCode,
 		tree(ElseCode,
 		tree(ElseSaveCode,
-		     EndLabelCode))))))))))))))))))))
+		     EndLabelCode)))))))))))))))))))
 	},
 	code_info__after_all_branches(StoreMap, MaybeEnd).
 
@@ -285,17 +279,12 @@
 	code_info__effect_resume_point(ResumePoint, CodeModel,
 		EffectResumeCode),
 
-	{ goal_may_hijack_top_redoip(Goal, MayHijack) },
-	code_info__maybe_push_temp_frame(CodeModel, MayHijack,
-		HijackInfo, CurFrameLval, TempFrameCode),
-
 		% Generate the negated goal as a semi-deterministic goal;
 		% it cannot be nondet, since mode correctness requires it
 		% to have no output vars.
 	code_gen__generate_goal(model_semi, Goal, GoalCode),
 
-	code_info__ite_enter_then(HijackInfo, CurFrameLval,
-		ThenNeckCode, ElseNeckCode),
+	code_info__ite_enter_then(HijackInfo, ThenNeckCode, ElseNeckCode),
 
 		% Kill again any variables that have become zombies
 	code_info__pickup_zombies(Zombies),
@@ -333,7 +322,6 @@
 		tree(FlushCode,
 		tree(PrepareHijackCode,
 		tree(EffectResumeCode,
-		tree(TempFrameCode,
 		tree(SaveHpCode,
 		tree(SaveTicketCode,
 		tree(GoalCode,
@@ -343,79 +331,7 @@
 		tree(ResumeCode,
 		tree(ElseNeckCode,
 		tree(RestoreTicketCode,
-		     RestoreHpCode)))))))))))))
+		     RestoreHpCode))))))))))))
 	}.
-
-%---------------------------------------------------------------------------%
-
-:- pred goal_may_hijack_top_redoip(hlds_goal::in, bool::out) is det.
-
-goal_may_hijack_top_redoip(GoalExpr - GoalInfo, MayHijack) :-
-	(
-		GoalExpr = conj(Conj),
-		goals_may_hijack_top_redoip(Conj, MayHijack)
-	;
-		GoalExpr = par_conj(Conj, _),
-		goals_may_hijack_top_redoip(Conj, MayHijack)
-	;
-		GoalExpr = call(_, _, _, _, _, _),
-		MayHijack = yes
-	;
-		GoalExpr = higher_order_call(_, _, _, _, _, _),
-		MayHijack = yes
-	;
-		GoalExpr = class_method_call(_, _, _, _, _, _),
-		MayHijack = yes
-	;
-		GoalExpr = switch(_, _, Cases, _),
-		cases_may_hijack_top_redoip(Cases, MayHijack)
-	;
-		GoalExpr = unify(_, _, _, _, _),
-		MayHijack = no
-	;
-		GoalExpr = disj(Disj, _),
-		(
-			goal_info_get_code_model(GoalInfo, CodeModel),
-			CodeModel = model_non
-		->
-			MayHijack = yes
-		;
-			goals_may_hijack_top_redoip(Disj, MayHijack)
-		)
-	;
-		GoalExpr = not(_SubGoal),
-		MayHijack = yes
-	;
-		GoalExpr = some(_, _SubGoal),
-		MayHijack = yes
-	;
-		GoalExpr = if_then_else(_, _, _, _, _),
-		MayHijack = yes
-	;
-		GoalExpr = pragma_c_code(_, _, _, _, _, _, _),
-		MayHijack = yes
-	).
-
-:- pred goals_may_hijack_top_redoip(list(hlds_goal)::in, bool::out) is det.
-
-goals_may_hijack_top_redoip([], no).
-goals_may_hijack_top_redoip([Goal | Goals], MayHijack) :-
-	goal_may_hijack_top_redoip(Goal, MayHijack0),
-	( MayHijack0 = yes ->
-		MayHijack = yes
-	;
-		goals_may_hijack_top_redoip(Goals, MayHijack)
-	).
-
-:- pred cases_may_hijack_top_redoip(list(case)::in, bool::out) is det.
-
-cases_may_hijack_top_redoip([], no).
-cases_may_hijack_top_redoip([case(_, Goal) | Goals], MayHijack) :-
-	goal_may_hijack_top_redoip(Goal, MayHijack0),
-	( MayHijack0 = yes ->
-		MayHijack = yes
-	;
-		cases_may_hijack_top_redoip(Goals, MayHijack)
-	).
 
 %---------------------------------------------------------------------------%
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.36
diff -u -u -r1.36 livemap.m
--- livemap.m	1998/07/20 10:00:56	1.36
+++ livemap.m	1998/07/27 07:06:22
@@ -166,12 +166,6 @@
 		Instrs = Instrs0,
 		DontValueNumber = DontValueNumber0
 	;
-		Uinstr0 = modframe(_),
-		Livemap = Livemap0,
-		Livevals = Livevals0,
-		Instrs = Instrs0,
-		DontValueNumber = DontValueNumber0
-	;
 		Uinstr0 = label(Label),
 		map__set(Livemap0, Label, Livevals0, Livemap),
 		Livevals = Livevals0,
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.226
diff -u -u -r1.226 llds.m
--- llds.m	1998/07/20 10:00:59	1.226
+++ llds.m	1998/07/27 07:07:34
@@ -164,10 +164,6 @@
 			% when trying to generate the next solution from this
 			% choice point.
 
-	;	modframe(code_addr)
-			% modframe(FailureContinuation) is the same as
-			% current_redoip = FailureContinuation.
-
 	;	label(label)
 			% Defines a label that can be used as the
 			% target of calls, gotos, etc.
@@ -323,7 +319,9 @@
 	.
 
 :- type nondet_frame_info
-	--->	temp_frame
+	--->	temp_frame(
+			temp_frame_type
+		)
 	;	ordinary_frame(
 			string, 		% Name of the predicate.
 			int,			% Number of framevar slots.
@@ -332,6 +330,20 @@
 						% (for use by a model_non
 						% pragma C code).
 		).
+
+	% Temporary frames on the nondet stack exist only to provide a failure
+	% environment, i.e. a place to store a redoip and a redofr. Accurate
+	% garbage collection and execution tracing need to know how to
+	% interpret the layout information associated with the label whose
+	% address is in the redoip slot. If the label is in a procedure that
+	% stores its variables on the nondet stack, the redofr slot will give
+	% the address of the relevant stack frame. If the label is in a
+	% procedure that stores its variables on the det stack, the temporary
+	% frame will contain an extra slot containing the address of the
+	% relevant frame on the det stack.
+:- type temp_frame_type
+	--->	det_stack_proc
+	;	nondet_stack_proc.
 
 	% Procedures defined by nondet pragma C codes must have some way of
 	% preserving information after a success, so that when control
Index: compiler/llds_common.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_common.m,v
retrieving revision 1.19
diff -u -u -r1.19 llds_common.m
--- llds_common.m	1998/07/20 10:01:01	1.19
+++ llds_common.m	1998/07/27 07:18:34
@@ -184,10 +184,6 @@
 		Instr = Instr0,
 		Info = Info0
 	;
-		Instr0 = modframe(_),
-		Instr = Instr0,
-		Info = Info0
-	;
 		Instr0 = label(_),
 		Instr = Instr0,
 		Info = Info0
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.86
diff -u -u -r1.86 llds_out.m
--- llds_out.m	1998/07/25 13:28:54	1.86
+++ llds_out.m	1998/07/27 07:07:10
@@ -744,11 +744,9 @@
 		;
 			Instr = mkframe(_, label(ContLabel))
 		;
-			Instr = modframe(label(ContLabel))
-		;
 			Instr = join_and_continue(_, ContLabel)
 		;
-			Instr = assign(redoip(lval(maxfr)), 
+			Instr = assign(redoip(lval(_)), 
 				const(code_addr_const(label(ContLabel))))
 		)
 	->
@@ -885,9 +883,6 @@
 	),
 	output_code_addr_decls(FailureContinuation, "", "", 0, _,
 		DeclSet1, DeclSet).
-output_instruction_decls(modframe(FailureContinuation), DeclSet0, DeclSet) -->
-	output_code_addr_decls(FailureContinuation, "", "", 0, _,
-		DeclSet0, DeclSet).
 output_instruction_decls(label(_), DeclSet, DeclSet) --> [].
 output_instruction_decls(goto(CodeAddr), DeclSet0, DeclSet) -->
 	output_code_addr_decls(CodeAddr, "", "", 0, _, DeclSet0, DeclSet).
@@ -1131,16 +1126,19 @@
 			io__write_string(");\n")
 		)
 	;
-		{ FrameInfo = temp_frame },
-		io__write_string("\tmktempframe("),
-		output_code_addr(FailCont),
-		io__write_string(");\n")
+		{ FrameInfo = temp_frame(Kind) },
+		(
+			{ Kind = det_stack_proc },
+			io__write_string("\tmkdettempframe("),
+			output_code_addr(FailCont),
+			io__write_string(");\n")
+		;
+			{ Kind = nondet_stack_proc },
+			io__write_string("\tmktempframe("),
+			output_code_addr(FailCont),
+			io__write_string(");\n")
+		)
 	).
-
-output_instruction(modframe(FailureContinuation), _) -->
-	io__write_string("\tmodframe("),
-	output_code_addr(FailureContinuation),
-	io__write_string(");\n").
 
 output_instruction(label(Label), ProfInfo) -->
 	output_label_defn(Label),
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.73
diff -u -u -r1.73 middle_rec.m
--- middle_rec.m	1998/07/20 10:01:12	1.73
+++ middle_rec.m	1998/07/27 07:23:14
@@ -393,7 +393,6 @@
 	middle_rec__find_used_registers_rval(Rval, Used1, 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(modframe(_), Used, Used).
 middle_rec__find_used_registers_instr(label(_), Used, Used).
 middle_rec__find_used_registers_instr(goto(_), Used, Used).
 middle_rec__find_used_registers_instr(computed_goto(Rval, _), Used0, Used) :-
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.83
diff -u -u -r1.83 opt_debug.m
--- opt_debug.m	1998/07/20 10:01:14	1.83
+++ opt_debug.m	1998/07/27 07:18:42
@@ -855,12 +855,16 @@
 		string__append_list(["mkframe(", Name, ", ", S_str, ", ",
 			P_str, ", ", R_str, ")"], Str)
 	;
-		FrameInfo = temp_frame,
-		string__append_list(["mktempframe(", R_str, ")"], Str)
+		FrameInfo = temp_frame(Kind),
+		(
+			Kind = nondet_stack_proc,
+			string__append_list(["mktempframe(", R_str, ")"], Str)
+		;
+			Kind = det_stack_proc,
+			string__append_list(["mkdettempframe(", R_str, ")"],
+				Str)
+		)
 	).
-opt_debug__dump_instr(modframe(Redoip), Str) :-
-	opt_debug__dump_code_addr(Redoip, R_str),
-	string__append_list(["modframe(", R_str, ")"], Str).
 opt_debug__dump_instr(label(Label), Str) :-
 	opt_debug__dump_label(Label, L_str),
 	string__append_list(["label(", L_str, ")"], Str).
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.94
diff -u -u -r1.94 opt_util.m
--- opt_util.m	1998/07/20 10:01:16	1.94
+++ opt_util.m	1998/07/27 11:28:45
@@ -47,12 +47,14 @@
 	list(instruction)).
 :- mode opt_util__skip_comments_livevals_labels(in, out) is det.
 
-	% Find the next modframe if it is guaranteed to be reached from here
+	% Find the next assignment to the redoip of the frame whose address
+	% is given by the base addresses in the second argument, provided
+	% it is guaranteed to be reached from here.
+
+:- pred opt_util__next_assign_to_redoip(list(instruction), list(lval),
+	list(instruction), code_addr, list(instruction), list(instruction)).
+:- mode opt_util__next_assign_to_redoip(in, in, in, out, out, out) is semidet.
 
-:- pred opt_util__next_modframe(list(instruction), list(instruction),
-	code_addr, list(instruction), list(instruction)).
-:- mode opt_util__next_modframe(in, in, out, out, out) is semidet.
-
 	% See if these instructions touch nondet stack controls, i.e.
 	% the virtual machine registers that point to the nondet stack
 	% (curfr and maxfr) and the fixed slots in nondet stack frames.
@@ -389,18 +391,13 @@
 		Instrs = Instrs0
 	).
 
-opt_util__next_modframe([Instr | Instrs], RevSkip, Redoip, Skip, Rest) :-
+opt_util__next_assign_to_redoip([Instr | Instrs], AllowedBases,
+		RevSkip, Redoip, Skip, Rest) :-
 	Instr = Uinstr - _Comment,
 	(
-		Uinstr = modframe(Redoip0)
-	->
-		Redoip = Redoip0,
-		list__reverse(RevSkip, Skip),
-		Rest = Instrs
-	;
 		Uinstr = assign(redoip(lval(Fr)),
 			const(code_addr_const(Redoip0))),
-		( Fr = maxfr ; Fr = curfr )
+		list__member(Fr, AllowedBases)
 	->
 		Redoip = Redoip0,
 		list__reverse(RevSkip, Skip),
@@ -412,8 +409,8 @@
 	;
 		opt_util__can_instr_branch_away(Uinstr, Canbranchaway),
 		( Canbranchaway = no ->
-			opt_util__next_modframe(Instrs, [Instr | RevSkip],
-				Redoip, Skip, Rest)
+			opt_util__next_assign_to_redoip(Instrs, AllowedBases,
+				[Instr | RevSkip], Redoip, Skip, Rest)
 		;
 			fail
 		)
@@ -778,9 +775,6 @@
 		Uinstr0 = mkframe(_, _),
 		Need = no
 	;
-		Uinstr0 = modframe(_),
-		Need = no
-	;
 		Uinstr0 = label(_),
 		Need = no
 	;
@@ -981,7 +975,6 @@
 opt_util__can_instr_branch_away(assign(_, _), no).
 opt_util__can_instr_branch_away(call(_, _, _, _), yes).
 opt_util__can_instr_branch_away(mkframe(_, _), no).
-opt_util__can_instr_branch_away(modframe(_), no).
 opt_util__can_instr_branch_away(label(_), no).
 opt_util__can_instr_branch_away(goto(_), yes).
 opt_util__can_instr_branch_away(computed_goto(_, _), yes).
@@ -1044,7 +1037,6 @@
 opt_util__can_instr_fall_through(assign(_, _), yes).
 opt_util__can_instr_fall_through(call(_, _, _, _), no).
 opt_util__can_instr_fall_through(mkframe(_, _), yes).
-opt_util__can_instr_fall_through(modframe(_), yes).
 opt_util__can_instr_fall_through(label(_), yes).
 opt_util__can_instr_fall_through(goto(_), no).
 opt_util__can_instr_fall_through(computed_goto(_, _), no).
@@ -1089,7 +1081,6 @@
 opt_util__can_use_livevals(assign(_, _), no).
 opt_util__can_use_livevals(call(_, _, _, _), yes).
 opt_util__can_use_livevals(mkframe(_, _), no).
-opt_util__can_use_livevals(modframe(_), no).
 opt_util__can_use_livevals(label(_), no).
 opt_util__can_use_livevals(goto(_), yes).
 opt_util__can_use_livevals(computed_goto(_, _), no).
@@ -1151,7 +1142,6 @@
 opt_util__instr_labels_2(assign(_,_), [], []).
 opt_util__instr_labels_2(call(Target, Ret, _, _), [], [Target, Ret]).
 opt_util__instr_labels_2(mkframe(_, Addr), [], [Addr]).
-opt_util__instr_labels_2(modframe(Addr), [], [Addr]).
 opt_util__instr_labels_2(label(_), [], []).
 opt_util__instr_labels_2(goto(Addr), [], [Addr]).
 opt_util__instr_labels_2(computed_goto(_, Labels), Labels, []).
@@ -1190,7 +1180,6 @@
 opt_util__instr_rvals_and_lvals(assign(Lval,Rval), [Rval], [Lval]).
 opt_util__instr_rvals_and_lvals(call(_, _, _, _), [], []).
 opt_util__instr_rvals_and_lvals(mkframe(_, _), [], []).
-opt_util__instr_rvals_and_lvals(modframe(_), [], []).
 opt_util__instr_rvals_and_lvals(label(_), [], []).
 opt_util__instr_rvals_and_lvals(goto(_), [], []).
 opt_util__instr_rvals_and_lvals(computed_goto(Rval, _), [Rval], []).
@@ -1313,7 +1302,6 @@
 	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(mkframe(_, _), R, R, F, F).
-opt_util__count_temps_instr(modframe(_), R, R, F, F).
 opt_util__count_temps_instr(label(_), R, R, F, F).
 opt_util__count_temps_instr(goto(_), R, R, F, F).
 opt_util__count_temps_instr(computed_goto(Rval, _), R0, R, F0, F) :-
Index: compiler/peephole.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/peephole.m,v
retrieving revision 1.75
diff -u -u -r1.75 peephole.m
--- peephole.m	1998/07/20 10:01:23	1.75
+++ peephole.m	1998/07/27 07:52:30
@@ -84,15 +84,14 @@
 
 %-----------------------------------------------------------------------------%
 
-		
 	% Look for code patterns that can be optimized, and optimize them.
 
 :- pred peephole__match(instr, string, list(pattern),
 		list(instruction), list(instruction)).
 :- mode peephole__match(in, in, in, in, out) is semidet.
 
-	% A `computed_goto' with all branches pointing to the same 
-	% label can be replaced with an unconditional goto. 
+	% A `computed_goto' with all branches pointing to the same
+	% label can be replaced with an unconditional goto.
 
 peephole__match(computed_goto(_, Labels), Comment, _, Instrs0, Instrs) :-
 	list__all_same(Labels),
@@ -134,15 +133,14 @@
 		fail
 	).
 
-	% If a `mkframe' is followed by a `modframe', with the instructions
-	% in between containing only straight-line code, we can delete the
-	% `modframe' and instead just set the redoip directly in the `mkframe'.
-	% This should also be done if the modframe appears instead as an
-	% assignment to the redoip of curfr or maxfr.
+	% If a `mkframe' is followed by an assignment to its redoip slot,
+	% with the instructions in between containing only straight-line code,
+	% we can delete the assignment and instead just set the redoip
+	% directly in the `mkframe'.
 	%
 	%	mkframe(NFI, _)		=>	mkframe(NFI, Redoip)
 	%	<straightline instrs>		<straightline instrs>
-	%	modframe(Redoip)
+	%	assign(redoip(lval(_)), Redoip)
 	%
 	% If a `mkframe' is followed by a test that can fail, we try to
 	% swap the two instructions to avoid doing the mkframe unnecessarily.
@@ -162,7 +160,15 @@
 peephole__match(mkframe(NondetFrameInfo, Redoip1), Comment, _,
 		Instrs0, Instrs) :-
 	(
-		opt_util__next_modframe(Instrs0, [], Redoip2, Skipped, Rest),
+		% A mkframe sets curfr to point to the new frame
+		% only for ordinary frames, not temp frames.
+		( NondetFrameInfo = ordinary_frame(_, _, _) ->
+			AllowedBases = [maxfr, curfr]
+		;
+			AllowedBases = [maxfr]
+		),
+		opt_util__next_assign_to_redoip(Instrs0, AllowedBases,
+			[], Redoip2, Skipped, Rest),
 		opt_util__touches_nondet_ctrl(Skipped, no)
 	->
 		list__append(Skipped, Rest, Instrs1),
@@ -225,29 +231,35 @@
 	Instrs1 = [reset_ticket(lval(Lval), _Reason) - _Comment2 | Instrs2],
 	Instrs = [store_ticket(Lval) - Comment | Instrs2].
 
-	% If a `modframe' is followed by another, with the instructions
-	% in between containing only straight-line code, we can delete
-	% one of the modframes:
+	% If an assignment to a redoip slot is followed by another, with
+	% the instructions in between containing only straight-line code,
+	% we can delete one of the asignments:
 	%
-	%	modframe(Redoip1)	=>	modframe(Redoip2)
+	%	assign(redoip(Fr), Redoip1) =>	assign(redoip(Fr), Redoip2)
 	%	<straightline instrs>		<straightline instrs>
-	%	modframe(Redoip2)
+	%	assign(redoip(Fr), Redoip2)
 
-	% If a modframe(do_fail) is followed by straight-line instructions
-	% except possibly for if_val with do_fail or do_redo as target,
-	% until a goto to do_succeed(no), and if the nondet stack linkages
-	% are not touched by the straight-line instructions, then we can
-	% discard the nondet stack frame early.
+	% If an assignment of do_fail to the redoip slot of the current frame
+	% is followed by straight-line instructions except possibly for if_val
+	% with do_fail or do_redo as target, until a goto to do_succeed(no),
+	% and if the nondet stack linkages are not touched by the
+	% straight-line instructions, then we can discard the nondet stack
+	% frame early.
 
-peephole__match(modframe(Redoip), Comment, _, Instrs0, Instrs) :-
+peephole__match(assign(redoip(lval(Base)), Redoip), Comment, _,
+		Instrs0, Instrs) :-
 	(
-		opt_util__next_modframe(Instrs0, [], Redoip2, Skipped, Rest),
+		opt_util__next_assign_to_redoip(Instrs0, [Base],
+			[], Redoip2, Skipped, Rest),
 		opt_util__touches_nondet_ctrl(Skipped, no)
 	->
 		list__append(Skipped, Rest, Instrs1),
-		Instrs = [modframe(Redoip2) - Comment | Instrs1]
+		Instrs = [assign(redoip(lval(Base)),
+			const(code_addr_const(Redoip2))) - Comment
+			| Instrs1]
 	;
-		Redoip = do_fail,
+		Base = curfr,
+		Redoip = const(code_addr_const(do_fail)),
 		opt_util__straight_alternative(Instrs0, Between, After),
 		opt_util__touches_nondet_ctrl(Between, no)
 	->
@@ -287,11 +299,11 @@
 	% Given a GC method, return the list of invalid peephole
 	% optimizations.
 
-:- pred peephole__invalid_opts(gc_method, list(pattern)). 
+:- pred peephole__invalid_opts(gc_method, list(pattern)).
 :- mode peephole__invalid_opts(in, out) is det.
 
 peephole__invalid_opts(GC_Method, InvalidPatterns) :-
-	( 
+	(
 		GC_Method = accurate
 	->
 		InvalidPatterns = [incr_sp]
Index: compiler/pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.16
diff -u -u -r1.16 pragma_c_gen.m
--- pragma_c_gen.m	1998/05/16 07:30:41	1.16
+++ pragma_c_gen.m	1998/07/27 08:23:34
@@ -513,8 +513,9 @@
 
 	code_info__get_next_label(RetryLabel),
 	{ ModFrameCode = node([
-		modframe(label(RetryLabel)) -
-			"Set up backtracking to retry label"
+		assign(redoip(lval(curfr)),
+			const(code_addr_const(label(RetryLabel))))
+			- "Set up backtracking to retry label"
 	]) },
 	{ RetryLabelCode = node([
 		label(RetryLabel) -
Index: compiler/value_number.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/value_number.m,v
retrieving revision 1.94
diff -u -u -r1.94 value_number.m
--- value_number.m	1998/07/20 10:01:39	1.94
+++ value_number.m	1998/07/27 07:03:09
@@ -406,10 +406,9 @@
 		{ value_number__push_decr_sp_back(Instrs1, Instrs2) },
 		{ value_number__push_incr_sp_forw(Instrs2, Instrs3) },
 		{ value_number__push_livevals_back(Instrs3, Instrs4) },
-		{ value_number__convert_back_modframe(Instrs4, Instrs5) },
-		{ vn_filter__block(Instrs5, Instrs6) },
+		{ vn_filter__block(Instrs4, Instrs5) },
 		globals__io_get_gc_method(GC_Method),
-		{ peephole__optimize(GC_Method, Instrs6, Instrs7, _) },
+		{ peephole__optimize(GC_Method, Instrs5, Instrs6, _) },
 
 		vn_debug__cost_header_msg("original code sequence"),
 		vn_cost__block_cost(Instrs0, Params, yes, OrigCost),
@@ -417,11 +416,11 @@
 			[]
 		;
 			vn_debug__cost_header_msg("unfiltered code sequence"),
-			vn_cost__block_cost(Instrs5, Params, yes, _)
+			vn_cost__block_cost(Instrs4, Params, yes, _)
 		),
 
 		vn_debug__cost_header_msg("new code sequence"),
-		vn_cost__block_cost(Instrs7, Params, yes, VnCost),
+		vn_cost__block_cost(Instrs6, Params, yes, VnCost),
 
 		globals__io_lookup_int_option(vn_fudge, VnFudge),
 
@@ -429,21 +428,21 @@
 			{ VnCost < OrigCost },
 			{
 				assoc_list__keys(Instrs0, Uinstrs0),
-				assoc_list__keys(Instrs7, Uinstrs7),
-				list__sublist(Uinstrs7, Uinstrs0)
+				assoc_list__keys(Instrs6, Uinstrs6),
+				list__sublist(Uinstrs6, Uinstrs0)
 			;
 				VnCost * 1000 < OrigCost * VnFudge
 			}
 		->
 			vn_debug__cost_msg(yes, OrigCost, VnCost),
-			{ vn_block__build_block_info(Instrs7, LiveMap, Params,
-				ParEntries, LabelNo0, VnTables7, Liveset7,
-				SeenIncr7, Tuple7) },
-			vn_verify__ok(Instrs7, Uinstr0, SeenIncr0, SeenIncr7,
-				Liveset0, Liveset7, VnTables0, VnTables7, OK),
+			{ vn_block__build_block_info(Instrs6, LiveMap, Params,
+				ParEntries, LabelNo0, VnTables6, Liveset6,
+				SeenIncr6, Tuple6) },
+			vn_verify__ok(Instrs6, Uinstr0, SeenIncr0, SeenIncr6,
+				Liveset0, Liveset6, VnTables0, VnTables6, OK),
 			( { OK = yes } ->
-				{ Instrs = Instrs7 },
-				{ Tuple = Tuple7 }
+				{ Instrs = Instrs6 },
+				{ Tuple = Tuple6 }
 			;
 				{ Instrs = Instrs0 },
 				{ Tuple = Tuple0 }
@@ -874,25 +873,6 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-:- pred value_number__convert_back_modframe(list(instruction),
-	list(instruction)).
-:- mode value_number__convert_back_modframe(in, out) is det.
-
-value_number__convert_back_modframe([], []).
-value_number__convert_back_modframe([Instr0 | Instrs0], [Instr | Instrs]) :-
-	value_number__convert_back_modframe(Instrs0, Instrs),
-	(
-		Instr0 = assign(redoip(lval(curfr)),
-			const(code_addr_const(Redoip))) - _
-	->
-		Instr = modframe(Redoip) - "recovered modframe"
-	;
-		Instr = Instr0
-	).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
 :- pred value_number__push_decr_sp_back(list(instruction), list(instruction)).
 % :- mode value_number__push_decr_sp_back(di, uo) is det.
 :- mode value_number__push_decr_sp_back(in, out) is det.
@@ -1074,10 +1054,14 @@
 value_number__boundary_instr(comment(_), no).
 value_number__boundary_instr(livevals(_), no).
 value_number__boundary_instr(block(_, _, _), no).
-value_number__boundary_instr(assign(_,_), no).
+value_number__boundary_instr(assign(Lval,_), Boundary) :-
+	( Lval = redoip(_) ->
+		Boundary = yes
+	;
+		Boundary = no
+	).
 value_number__boundary_instr(call(_, _, _, _), yes).
 value_number__boundary_instr(mkframe(_, _), yes).
-value_number__boundary_instr(modframe(_), yes).
 value_number__boundary_instr(label(_), yes).
 value_number__boundary_instr(goto(_), yes).
 value_number__boundary_instr(computed_goto(_, _), yes).
Index: compiler/vn_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_block.m,v
retrieving revision 1.55
diff -u -u -r1.55 vn_block.m
--- vn_block.m	1998/07/20 10:01:41	1.55
+++ vn_block.m	1998/07/27 07:05:01
@@ -241,13 +241,6 @@
 		const(code_addr_const(Redoip))),
 		Livemap, Params, VnTables1, VnTables, Liveset1, Liveset,
 		SeenIncr0, SeenIncr, Tuple1, Tuple).
-vn_block__handle_instr(modframe(Redoip), Livemap, Params,
-		VnTables0, VnTables, Liveset0, Liveset,
-		SeenIncr0, SeenIncr, Tuple0, Tuple) :-
-	vn_block__handle_instr(assign(redoip(lval(curfr)),
-		const(code_addr_const(Redoip))),
-		Livemap, Params, VnTables0, VnTables, Liveset0, Liveset,
-		SeenIncr0, SeenIncr, Tuple0, Tuple).
 vn_block__handle_instr(label(Label),
 		Livemap, Params, VnTables0, VnTables, Liveset0, Liveset,
 		SeenIncr, SeenIncr, Tuple0, Tuple) :-
@@ -894,7 +887,6 @@
 vn_block__is_ctrl_instr(assign(_, _), no).
 vn_block__is_ctrl_instr(call(_, _, _, _), yes).
 vn_block__is_ctrl_instr(mkframe(_, _), yes).
-vn_block__is_ctrl_instr(modframe(_), no).
 vn_block__is_ctrl_instr(label(_), yes).
 vn_block__is_ctrl_instr(goto(_), yes).
 vn_block__is_ctrl_instr(computed_goto(_, _), yes).
Index: compiler/vn_cost.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_cost.m,v
retrieving revision 1.34
diff -u -u -r1.34 vn_cost.m
--- vn_cost.m	1998/07/20 10:01:42	1.34
+++ vn_cost.m	1998/07/27 07:05:06
@@ -114,9 +114,6 @@
 		Uinstr = mkframe(_, _),
 		Cost = 0
 	;
-		Uinstr = modframe(_),
-		Cost = 0
-	;
 		Uinstr = label(_),
 		Cost = 0
 	;
Index: compiler/vn_filter.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_filter.m,v
retrieving revision 1.19
diff -u -u -r1.19 vn_filter.m
--- vn_filter.m	1998/07/20 10:01:44	1.19
+++ vn_filter.m	1998/07/27 07:05:23
@@ -137,7 +137,6 @@
 vn_filter__user_instr(assign(_, Rval), yes(Rval)).
 vn_filter__user_instr(call(_, _, _, _), no).
 vn_filter__user_instr(mkframe(_, _), no).
-vn_filter__user_instr(modframe(_), no).
 vn_filter__user_instr(label(_), no).
 vn_filter__user_instr(goto(_), no).
 vn_filter__user_instr(computed_goto(Rval, _), yes(Rval)).
@@ -186,8 +185,6 @@
 	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").
-vn_filter__replace_in_user_instr(modframe(_), _, _, _) :-
-	error("non-user instruction in vn_filter__replace_in_user_instr").
 vn_filter__replace_in_user_instr(label(_), _, _, _) :-
 	error("non-user instruction in vn_filter__replace_in_user_instr").
 vn_filter__replace_in_user_instr(goto(_), _, _, _) :-
@@ -247,7 +244,6 @@
 vn_filter__defining_instr(assign(Lval, _), yes(Lval)).
 vn_filter__defining_instr(call(_, _, _, _), no).
 vn_filter__defining_instr(mkframe(_, _), no).
-vn_filter__defining_instr(modframe(_), no).
 vn_filter__defining_instr(label(_), no).
 vn_filter__defining_instr(goto(_), no).
 vn_filter__defining_instr(computed_goto(_, _), no).
@@ -295,8 +291,6 @@
 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").
-vn_filter__replace_in_defining_instr(modframe(_), _, _, _) :-
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
 vn_filter__replace_in_defining_instr(label(_), _, _, _) :-
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
Index: compiler/vn_verify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_verify.m,v
retrieving revision 1.18
diff -u -u -r1.18 vn_verify.m
--- vn_verify.m	1998/07/20 10:01:52	1.18
+++ vn_verify.m	1998/07/27 07:05:43
@@ -303,10 +303,6 @@
 		NoDeref = NoDeref0,
 		Tested = Tested0
 	;
-		Instr = modframe(_),
-		NoDeref = NoDeref0,
-		Tested = Tested0
-	;
 		Instr = label(_),
 		NoDeref = NoDeref0,
 		Tested = Tested0
cvs diff: Diffing compiler/notes
Index: compiler/notes/failure.html
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/notes/failure.html,v
retrieving revision 1.3
diff -u -u -r1.3 failure.html
--- failure.html	1998/07/20 10:02:50	1.3
+++ failure.html	1998/07/27 11:22:32
@@ -1,7 +1,7 @@
 <html>
 <head>
 <title>
-	Management of failure in the code generator
+Management of failure in the code generator
 </title>
 </head>
 
@@ -27,8 +27,8 @@
 
 <h2> RUNTIME DATA STRUCTURES </h2>
 
-In the current design of the nondet stack, two registers point to
-nondet stack frames.
+In the design of the nondet stack,
+two registers point to nondet stack frames.
 
 <p>
 
@@ -38,7 +38,7 @@
 <p>
 <li>
 While executing a model_non procedure,
-the curfr register points to the nondet stack frame of that procedure.
+the curfr register points to the ordinary nondet stack frame of that procedure.
 While executing a model_det or model_semi procedure,
 the curfr register points to the nondet stack frame
 of the nearest model_non ancestor of that procedure.
@@ -48,39 +48,57 @@
 
 <p>
 
-Each nondet stack frame contains four fixed fields:
+Each ordinary nondet stack frame contains five fixed slots:
 
 <p>
 
 <ul>
+<li>	prevfr, the address of the previous frame on the nondet stack
+<li>	redoip, the label to go to when backtracking reaches this frame
+<li>	redofr, the value to set curfr to when backtracking through redoip
 <li>	succip, the label to go to on success
 <li>	succfr, the value to reset curfr to on success (frame of our caller)
-<li>	redoip, the label to go to when backtracking reaches this frame
-<li>	prevfr, the address of the previous frame on the nondet stack
 </ul>
 
 <p>
 
-The redo() macro is implemented as
+Ordinary nondet stack frames may also contain the values of variables
+and/or temporary values such as saved trail pointers.
 
 <p>
 
-<pre>
-curfr = maxfr;
-goto *redoip_slot(maxfr);
-</pre>
+All temporary nondet stack frames
+contain the three fixed slots, prevfr, redoip and redofr.
+Temporary frames created by model_det and model_semi procedures
+also have a fourth fixed slot, detfr, which points to the stack frame
+(on the det stack) of the procedure that created them.
+Temporary nondet stack frames
+never contain any slots except these fixed slots.
+Therefore for any given nondet frame its size determines its type.
+If this is three words,
+it is a temporary frame created by a model_non procedure;
+if this is four words,
+it is a temporary frame created by a model_det or model_semi procedure;
+if this is five words or more,
+it is an ordinary frame.
 
 <p>
 
-while the fail() macro discards the top nondet stack frame and then executes
-a redo().
+The fixed slots prevfr, redoip and redofr
+are present in all nondet stack frames, ordinary and temporary,
+at the same offset and with the same semantics.
+Therefore code that accesses only these fields of a nondet stack frame
+does not need to find out what kind of frame it is.
+
+<p>
+
+The detfr slot is for the acurate garbage collector;
+it is never used by the backtracking mechanism.
+Therefore in the following we can and will treat all temporary frames the same.
 
 <p>
 
-The proposed design extends each nondet stack frame with a fifth fixed field,
-redofr (it gives the frame corresponding to the label in the redoip slot).
-When a frame is created, the redofr slot is initialized to point to the
-frame itself. The redo macro is redefined as
+The redo() macro is implemented as
 
 <p>
 
@@ -91,24 +109,27 @@
 
 <p>
 
-The purpose of the new slot is to allow the code generator to hijack the
-redoip slots of frames without jumping through hoops to arrange for curfr
-to be set correctly whenever execution backtracks through hijacked redoip
-slots. With the new design, the code generator can simply hijack the redofr
-field as well.
+while the fail() macro discards the top nondet stack frame and then executes
+a redo().
 
 <p>
 
+It is an invariant that
+curfr will always point to an ordinary nondet stack frame;
+it will never point to a temporary frame.
+
+<p>
+
 It is an invariant that for any nondet stack frame whose address is frame_addr,
 redofr_slot(frame_addr) == frame_addr whenever curfr == frame_addr. However,
 it is possible that redofr_slot(frame_addr) != frame_addr at other times.
 
 <p>
 
-One implication of the change is that at a point in the code where execution
-may resume after a redo(), the code of a procedure can assume that
-curfr == maxfr at that point only if it did not hijack any frames
-anywhere to the left of that point.
+One implication of this possibility is that
+at a point in the code where execution may resume after a redo(),
+the code of a procedure can assume that curfr == maxfr at that point
+only if it did not hijack any frames anywhere to the left of that point.
 
 <h2> CODE GENERATOR DATA STRUCTURES </h2>
 
@@ -160,23 +181,26 @@
 
 <p>
 
-The left context has two subfields.
+The left context has three subfields.
 
 <p>
 
 <ul>
 <li>
-The resume_point_known subfield says
-whether the code generator knows what label to branch to on failure.
+The resume_point_known subfield can take on
+one of the two values known and unknown,
+saying whether the code generator knows what label to branch to on failure.
 The answer is yes if there is no nondet code between
-the establishment of the latest (tightest enclosing) resume point
+the establishment of the tightest enclosing resume point
 and the start of the current goal.
 
 <p>
 
 <li>
-The curfr_is_maxfr subfield says
-whether the code generator knows that curfr is guaranteed to be equal to maxfr.
+The curfr_maxfr subfield can take on
+one of the two values must_be_equal and may_be_different,
+saying whether the code generator knows that
+curfr is guaranteed to be equal to maxfr.
 The answer is yes if all of the following conditions hold:
 
 	<ul>
@@ -189,43 +213,60 @@
 	the start of the procedure and the start of the current goal; and
 	<li>
 	the code generator itself hasn't pushed any temporary nondet
-	stack frames (see nondet if-then-elses below).
+	stack frames (see below).
 	</ul>
+
+<li>
+The hijacks_allowed subfield can take on
+one of the two values allowed and not_allowed,
+saying whether the code generator is allowed to hijack
+the redoip and redofr slots of the top nondet stack frame.
 </ul>
 
 <p>
 
-The resume_point_known subfield is initialized to yes in all procedures.
-curfr_is_maxfr is initialized to yes in procedures whose prologues create
-a nondet stack frame, and to no in other procedures.
+The resume_point_known subfield is initialized to known in all procedures.
+curfr_maxfr is initialized to must_be_equal in model_non procedures,
+and to may_be_different in other procedures.
+The hijacks_allowed subfield is initialized to not_allowed
+if the compiler is given the --no-allow-hijacks compiler option,
+and to allowed otherwise.
+Grades that call for accurate garbage collection imply --no-allow-hijacks.
 
 <p>
 
 When the code generator processes any nondet goal,
-it must set the resume_point_known subfield to no at the end of the goal.
+it must set the resume_point_known subfield to unknown at the end of the goal.
 
 <p>
 
-When the code generator processes a nondet construct that leaves this procedure
-(i.e. a call or higher order call), it must set both subfields to no
+When the code generator processes a model_non construct
+that leaves this procedure (i.e. a call, higher order call or method call),
+it must also set the curfr_maxfr subfield to may_be_different
 at the end of the goal.
+(Since a model_non procedure can remove its own stack frame
+just before it succeeds for the last time,
+we can't say that after a call to such a procedure
+maxfr *will* be different from curfr.
 
 <p>
 
 When the code generator processes branched structures (if-then-elses,
-switches or disjunctions), if resume_point_known is no at the end of
-any arm, it must be no after the branched structure, and if curfr_is_maxfr
-is no at the end of any arm, it must also be no after the branched structure.
+switches or disjunctions), if resume_point_known is unknown at the end of
+any arm, it must be unknown after the branched structure, and if curfr_maxfr
+is may_be_different at the end of any arm, it must also be may_be_different
+after the branched structure.
 
 <p>
 
 When the code generator establishes a new resumption point,
-it may set the resume_point_known subfield to yes,
-but it may not set the curfr_is_maxfr subfield to yes.
+it will set the resume_point_known subfield to known,
+but it must not set the curfr_maxfr subfield to must_be_equal.
 
 <p>
 
-Note that in the absence of nondet code, both subfields will always be yes.
+Note that in the absence of model_non code, the resume_point_known subfield
+will always have the value known.
 
 <h3> Generating failure </h3>
 
@@ -255,45 +296,70 @@
 
 <ul>
 <li>
-We never generate redo() for failure if resume_point_known is yes,
-and we always generate redo() for failure if resume_point_known is no.
+We never generate redo() for failure if resume_point_known is known,
+and we always generate redo() for failure if resume_point_known is unknown.
 
 <p>
 
 <li>
-At all points when resume_point_known goes from yes to no,
+At all points when resume_point_known goes from known to unknown,
 we make sure that the resume variables are flushed to their stack slots.
 
 <p>
 
 <li>
 If, while a resumption point is active,
-control can reach a point where resume_point_known goes from yes to no,
-the resumption point must include a stack label.
+control can reach a point where resume_point_known goes from known to unknown,
+liveness.m ensures that the resumption point includes a stack label.
 </ul>
 
 <h3> Classifying left contexts </h3>
 
-In many cases, the code generator classifies left contexts into three cases:
+In many cases, the code generator classifies left contexts into four cases:
 
 <p>
 
 <ul>
-<li> best case: resume_point_known and curfr_is_maxfr are both yes
-<li> middle case: resume_point_known is no but curfr_is_maxfr is yes
-<li> worst case: curfr_is_maxfr is no
+<li> no-hijack case: hijacks_allowed is not allowed
+<li> best case: hijacks_allowed is allowed,
+resume_point_known is known and curfr_maxfr is must_be_equal
+<li> middle case: hijacks_allowed is allowed,
+resume_point_known is unknown and curfr_maxfr is must_be_equal
+<li> worst case: hijacks_allowed is allowed and curfr_maxfr is may_be_different
 </ul>
 
 <p>
+
+The code generator can treat any situation as a no-hijack case,
+it can treat best case as either middle case or worst case,
+and it can treat middle case as worst case.
+However, it should be able to generate better code
+if it exploits the available information.
+
+<p>
 
-The code generator can treat any situation as worst case,
-but it can generate better code if it exploits the available information.
+It may be that no-hijack case yields better code than worst case;
+this should be investigated XXX.
 
 <h2> HANDLING DISJUNCTIONS </h2>
 
 <h3> Handling nondet disjunctions </h3>
 
 <ul>
+<li> No-hijack case.
+Before entering the disjunction,
+the code generator creates a temporary nondet stack frame.
+When the code generator enters a nonlast disjunct,
+it pushes a new entry on the resume point stack
+indicating the resume point at the start of the next disjunct,
+and sets the redoip slot of the top frame (which is the temporary frame)
+to the stack continuation in that resume point.
+When the code generator enters the last disjunct,
+it does not push any entry on the resume point stack,
+and sets maxfr to the value
+in the prevfr slot of the top frame (which is the temporary frame),
+which pops the temporary frame off the stack.
+
 <li> Best case.
 When the code generator enters a nonlast disjunct,
 it pushes a new entry on the resume point stack
@@ -358,8 +424,8 @@
 
 <p>
 
-In the case of all these hijackings, the choices represented by the hijacked
-redoip and maybe redofr slots cannot be backtracked to until the disjunct
+For all the hijacking cases, the choices represented by the hijacked
+redoip and maybe redofr slots cannot be backtracked to until the disjunction
 that we are generating code for has failed. This cannot happen until the
 last disjunct has failed, by which time the slots must have been restored.
 This maintains the invariant that for any nondet stack frame whose address
@@ -379,6 +445,22 @@
 <h3> Handling nondet if-then-elses with nondet conditions </h3>
 
 <ul>
+<li> No-hijack case.
+Before the code generator enters the condition,
+the code generator creates a temporary nondet stack frame,
+and saves the address of this temporary frame in a stack slot.
+It also pushes a new entry on the resume point stack
+indicating the resume point at the start of the else part,
+and sets the redoip slot of the top frame (which must be the temporary frame)
+to the stack continuation in that resume point.
+After the code generator emerges from the condition,
+it pops the new entry off the resume point stack.
+Before entry to the then part or to the else part,
+it assigns do_fail to the redoip slot of the temporary frame
+(pointed to by the stack slot), effectively removing the temporary frame.
+(We cannot generate code to pop the frame off the stack,
+since it may not be on top.)
+
 <li> Best case.
 Before the code generator enters the condition,
 it pushes a new entry on the resume point stack
@@ -440,18 +522,21 @@
 
 <p>
 
-If the condition may perform a hijacking
-(i.e. if it contains a nondet disjunction, nondet if-then-else
-or a commit across a nondet -as opposed to multi- goal),
-the hijacking we do for the soft cut of the if-then-else
-may overwrite the same slots used by the hijacking inside the condition.
-We avoid this by pushing a temporary frame onto the nondet stack
-just before entering the condition;
-any hijacks inside the condition will hijack the slots of this frame.
-The temporary frame has only the prevfr, redoip and redofr slots;
-the redoip slot is initialized to do_fail and the redofr slot to curfr.
-The presence of this frame on top of ours then requires us
-to set curfr_is_maxfr to no before entering the condition.
+All these four manipulate the redoip slot of the nondet stack frame
+that is on top of the nondet stack when execution enters the condition.
+On entry to the condition, we set it to point the start of the else part;
+on exit from the condition, we reset it to some other value to prevent
+backtracking to the else part.
+If the condition hijacks this slot, this scheme will not work.
+(Although the code that hijacks the slot
+will restore it to its original value before finally failing,
+that is too late in this case.)
+Therefore before entering the condition,
+the code generator sets the hijacks_allowed subfield to not_allowed; 
+on exit from the condition, it restores the original value.
+(This is the only time the value of hijacks_allowed is ever changed,
+so if hijacks_allowed starts out as not_allowed,
+it will always stay not_allowed.)
 
 <p>
 
@@ -461,15 +546,15 @@
 does not apply to failures in the then part. Therefore before entering the
 then part, the code generator will reset resume_point_known to the value
 it had before entering the if-then-else, except if resume_point_known
-has become no during the generation of code for the condition, in which
-case it will continue to be no.
+has become unknown during the generation of code for the condition, in which
+case it will continue to be unknown.
 
 <h3> Handling nondet if-then-elses with semi or det conditions </h3>
 
 We can handle these as we handle nondet if-then-elses with nondet conditions,
 or we can handle them as we handle semi or det if-then-elses, with the
 exception that we generate the then part and the else part as nondet goals.
-The latter will be more efficient.
+The latter is more efficient, so that is what we do.
 
 <h3> Handling semi or det if-then-elses </h3>
 
@@ -489,6 +574,19 @@
 <h3> Handling commits across nondet goals </h3>
 
 <ul>
+<li> No-hijack case.
+Before the code generator enters a goal that is being committed across,
+it saves the value of maxfr in a stack slot,
+and then it creates a temporary nondet stack frame
+whose redoip slot points to the resume point
+for getting control back if the goal has no solutions.
+It also pushes a new entry on the resume point stack
+indicating this resume point.
+The code at this resume point will perform a failure in the manner
+appropriate for whatever entry was originally on top of the resume point stack.
+Both continuations will reset maxfr
+to the value it had originally, which is in that stack slot.
+
 <li> Best case.
 Before the code generator enters a goal that is being committed across,
 it pushes a new entry on the resume point stack indicating
@@ -555,7 +653,7 @@
 Since we are cutting away any frames created by the goal being committed
 across, and since any resumption points established in that goal cannot
 survive across the commit, at the end of processing the commit we can reset
-both curfr_is_maxfr and resume_point_known to their values before the commit.
+both curfr_maxfr and resume_point_known to their values before the commit.
 
 <p>
 
@@ -572,11 +670,11 @@
 
 <ul>
 <li>
-If curfr_is_maxfr is yes.
-The code after the goal will reset maxfr to curfr.
+If curfr_maxfr is must_be_equal,
+the code after the goal will reset maxfr to curfr.
 <li>
-If curfr_is_maxfr is no.
-Before the code generator enters a goal that is being committed across,
+If curfr_maxfr is may_be_different,
+then before the code generator enters a goal that is being committed across,
 it saves the value of maxfr in a stack slot.
 The code after the goal will reset maxfr to the saved value.
 </ul>
cvs diff: Diffing doc
cvs diff: Diffing extras
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/exceptions
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/Togl-1.2
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/odbc
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 library
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/mercury_debug.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_debug.h,v
retrieving revision 1.4
diff -u -u -r1.4 mercury_debug.h
--- mercury_debug.h	1998/03/16 12:23:25	1.4
+++ mercury_debug.h	1998/07/27 07:17:30
@@ -46,7 +46,6 @@
 #define	debugregs(msg)				((void)0)
 #define	debugframe(msg)				((void)0)
 #define	debugmkframe()				((void)0)
-#define	debugmodframe()				((void)0)
 #define	debugsucceed()				((void)0)
 #define	debugsucceeddiscard()			((void)0)
 #define	debugfail()				((void)0)
@@ -95,9 +94,6 @@
 
 #define	debugframe(msg)	 \
 	IF (progdebug, (save_transient_registers(), printframe(msg)))
-
-#define	debugmodframe() \
-	IF (nondstackdebug, (save_transient_registers(), modframe_msg()))
 
 #define	debugsucceed() \
 	IF (nondstackdebug, (save_transient_registers(), succeed_msg()))
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.c,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_misc.c
--- mercury_misc.c	1998/07/07 08:04:13	1.9
+++ mercury_misc.c	1998/07/27 07:17:49
@@ -41,21 +41,6 @@
 }
 
 void 
-modframe_msg(void)
-{
-	restore_transient_registers();
-
-	printf("\nmodifying choice point for procedure %s\n", curprednm);
-	printf("redo ip: "); printlabel(curredoip);
-
-	if (detaildebug) {
-		dumpnondstack();
-	}
-
-	return;
-}
-
-void 
 succeed_msg(void)
 {
 	restore_transient_registers();
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.h,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_misc.h
--- mercury_misc.h	1998/07/03 02:35:19	1.7
+++ mercury_misc.h	1998/07/27 07:17:57
@@ -18,7 +18,6 @@
 
 #ifdef MR_LOWLEVEL_DEBUG
 extern	void	mkframe_msg(void);
-extern	void	modframe_msg(void);
 extern	void	succeed_msg(void);
 extern	void	succeeddiscard_msg(void);
 extern	void	fail_msg(void);
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.15
diff -u -u -r1.15 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/07/26 08:38:36	1.15
+++ mercury_stack_trace.c	1998/07/26 10:36:31
@@ -175,8 +175,8 @@
 		*stack_trace_sp_ptr = *stack_trace_sp_ptr -
 			entry_layout->MR_sle_stack_slots;
 	} else {
-		success = bt_succip(*stack_trace_curfr_ptr);
-		*stack_trace_curfr_ptr = bt_succfr(*stack_trace_curfr_ptr);
+		success = MR_succip_slot(*stack_trace_curfr_ptr);
+		*stack_trace_curfr_ptr = MR_succfr_slot(*stack_trace_curfr_ptr);
 	}
 
 	if (success == MR_stack_trace_bottom) {
@@ -201,6 +201,8 @@
 void
 MR_dump_nondet_stack_from_layout(FILE *fp, Word *base_maxfr)
 {
+	int	frame_size;
+
 	/*
 	** Change the >= below to > if you don't want the trace to include
 	** the bottom frame created by mercury_wrapper.c (whose redoip/redofr
@@ -208,22 +210,34 @@
 	*/
 
 	while (base_maxfr >= MR_nondet_stack_trace_bottom) {
-		if ((base_maxfr - bt_prevfr(base_maxfr)) < NONDET_FIXED_SIZE) {
-			fprintf(fp, "%p: temp\n", base_maxfr);
+		frame_size = base_maxfr - MR_prevfr_slot(base_maxfr);
+		if (frame_size == MR_NONDET_TEMP_SIZE) {
+			fprintf(fp, "%p: nondet temp\n", base_maxfr);
+			fprintf(fp, " redoip: ");
+			printlabel(MR_redoip_slot(base_maxfr));
+			fprintf(fp, " redofr: %p\n",
+				MR_redofr_slot(base_maxfr));
+		} else if (frame_size == MR_DET_TEMP_SIZE) {
+			fprintf(fp, "%p: nondet temp\n", base_maxfr);
 			fprintf(fp, " redoip: ");
-			printlabel(bt_redoip(base_maxfr));
-			fprintf(fp, " redofr: %p\n", bt_redofr(base_maxfr));
+			printlabel(MR_redoip_slot(base_maxfr));
+			fprintf(fp, " redofr: %p\n",
+				MR_redofr_slot(base_maxfr));
+			fprintf(fp, " detfr:  %p\n",
+				MR_detfr_slot(base_maxfr));
 		} else {
 			fprintf(fp, "%p: ordinary\n", base_maxfr);
 			fprintf(fp, " redoip: ");
-			printlabel(bt_redoip(base_maxfr));
-			fprintf(fp, " redofr: %p\n", bt_redofr(base_maxfr));
+			printlabel(MR_redoip_slot(base_maxfr));
+			fprintf(fp, " redofr: %p\n",
+				MR_redofr_slot(base_maxfr));
 			fprintf(fp, " succip: ");
-			printlabel(bt_succip(base_maxfr));
-			fprintf(fp, " succfr: %p\n", bt_succfr(base_maxfr));
+			printlabel(MR_succip_slot(base_maxfr));
+			fprintf(fp, " succfr: %p\n",
+				MR_succfr_slot(base_maxfr));
 		}
 
-		base_maxfr = bt_prevfr(base_maxfr);
+		base_maxfr = MR_prevfr_slot(base_maxfr);
 	}
 }
 
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_stacks.h
--- mercury_stacks.h	1998/07/20 10:03:33	1.7
+++ mercury_stacks.h	1998/07/27 07:16:36
@@ -74,32 +74,40 @@
 
 /* DEFINITIONS FOR NONDET STACK FRAMES */
 
-#define	PREVFR		(-0)	/* prev frame on stack, set up at call	*/
-#define	REDOIP		(-1)	/* in this proc, set up at clause entry	*/
-#define	REDOFR		(-2)	/* value for curfr on backtracking      */
-#define	SUCCIP		(-3)	/* in caller proc, set up at call	*/
-#define	SUCCFR		(-4)	/* frame of caller proc, set up at call	*/
+#define	MR_PREVFR	(-0)	/* prev frame on stack, set up at call	*/
+#define	MR_REDOIP	(-1)	/* in this proc, set up at clause entry	*/
+#define	MR_REDOFR	(-2)	/* value for curfr on backtracking      */
+#define	MR_SUCCIP	(-3)	/* in caller proc, set up at call	*/
+#define	MR_SUCCFR	(-4)	/* frame of caller proc, set up at call	*/
+#define	MR_DETFR	(-3)	/* sp, in model_det temp frames only	*/
 
 #ifdef MR_DEBUG_NONDET_STACK
-  #define PREDNM		(-5)	/* for debugging, set up at call */
-  #define MR_prednm(fr)		LVALUE_CAST(const char *, ((Word *) fr)[PREDNM])
-  #define NONDET_FIXED_SIZE	6	/* units: words */
+  #define MR_PREDNM		(-5)	/* for debugging, set up at call */
+  #define MR_prednm_slot(fr)	LVALUE_CAST(const char *, ((Word *) fr)[PREDNM])
+  #define MR_NONDET_FIXED_SIZE	6	/* units: words */
 #else
-  #define MR_prednm(fr)	"unknown"
-  #define NONDET_FIXED_SIZE	5	/* units: words */
+  #define MR_prednm_slot(fr)	"unknown"
+  #define MR_NONDET_FIXED_SIZE	5	/* units: words */
 #endif
 
-#define	NONDET_TEMP_SIZE	3	/* prevfr, redoip, redofr */
+/*
+** Code that traverses the nondet stack depends on the relationship
+** MR_NONDET_TEMP_SIZE < MR_DET_TEMP_SIZE < MR_NONDET_FIXED_SIZE.
+*/
 
-#define	SAVEVAL			(-NONDET_FIXED_SIZE)
+#define	MR_NONDET_TEMP_SIZE	3	/* prevfr, redoip, redofr */
+#define	MR_DET_TEMP_SIZE	4	/* prevfr, redoip, redofr, detfr */
+
+#define	MR_SAVEVAL			(-MR_NONDET_FIXED_SIZE)
 				/* saved values start at this offset	*/
 
-#define	MR_prevfr_slot(fr)	LVALUE_CAST(Word *, ((Word *) (fr))[PREVFR])
-#define	MR_redoip_slot(fr)	LVALUE_CAST(Code *, ((Word *) (fr))[REDOIP])
-#define	MR_redofr_slot(fr)	LVALUE_CAST(Word *, ((Word *) (fr))[REDOFR])
-#define	MR_succip_slot(fr)	LVALUE_CAST(Code *, ((Word *) (fr))[SUCCIP])
-#define	MR_succfr_slot(fr)	LVALUE_CAST(Word *, ((Word *) (fr))[SUCCFR])
-#define	MR_based_framevar(fr,n)	(((Word *) (fr))[SAVEVAL+1-(n)])
+#define	MR_prevfr_slot(fr)	LVALUE_CAST(Word *, ((Word *) (fr))[MR_PREVFR])
+#define	MR_redoip_slot(fr)	LVALUE_CAST(Code *, ((Word *) (fr))[MR_REDOIP])
+#define	MR_redofr_slot(fr)	LVALUE_CAST(Word *, ((Word *) (fr))[MR_REDOFR])
+#define	MR_succip_slot(fr)	LVALUE_CAST(Code *, ((Word *) (fr))[MR_SUCCIP])
+#define	MR_succfr_slot(fr)	LVALUE_CAST(Word *, ((Word *) (fr))[MR_SUCCFR])
+#define	MR_detfr_slot(fr)	LVALUE_CAST(Word *, ((Word *) (fr))[MR_DETFR])
+#define	MR_based_framevar(fr,n)	(((Word *) (fr))[MR_SAVEVAL+1-(n)])
 
 #define	bt_prevfr(fr)		MR_prevfr_slot(fr)
 #define	bt_redoip(fr)		MR_redoip_slot(fr)
@@ -126,106 +134,115 @@
 /* DEFINITIONS FOR MANIPULATING THE NONDET STACK */
 
 #ifdef MR_DEBUG_NONDET_STACK
-  #define mkframe_save_prednm(prednm) (curprednm = prednm)
+  #define mkframe_save_prednm(prednm) (MR_prednm_slot(MR_curfr) = prednm)
 #else
   #define mkframe_save_prednm(prednm) /* nothing */
 #endif
 
-#define	mkframe(prednm, numslots, redoip)			\
-			do {					\
-				reg	Word	*prevfr;	\
-				reg	Word	*succfr;	\
-								\
-				prevfr = MR_maxfr;		\
-				succfr = MR_curfr;		\
-				MR_maxfr += (NONDET_FIXED_SIZE + numslots);\
-				MR_curfr = MR_maxfr;		\
-				curredoip = redoip;		\
-				curprevfr = prevfr;		\
-				cursuccip = MR_succip;		\
-				cursuccfr = succfr;		\
-				curredofr = MR_curfr;		\
-				mkframe_save_prednm(prednm);	\
-				debugmkframe();			\
-				nondstack_overflow_check();	\
+#define	mkframe(prednm, numslots, redoip)				\
+			do {						\
+				reg	Word	*prevfr;		\
+				reg	Word	*succfr;		\
+									\
+				prevfr = MR_maxfr;			\
+				succfr = MR_curfr;			\
+				MR_maxfr += (MR_NONDET_FIXED_SIZE + numslots);\
+				MR_curfr = MR_maxfr;			\
+				MR_redoip_slot(MR_curfr) = redoip;	\
+				MR_prevfr_slot(MR_curfr) = prevfr;	\
+				MR_succip_slot(MR_curfr) = MR_succip;	\
+				MR_succfr_slot(MR_curfr) = succfr;	\
+				MR_redofr_slot(MR_curfr) = MR_curfr;	\
+				mkframe_save_prednm(prednm);		\
+				debugmkframe();				\
+				nondstack_overflow_check();		\
 			} while (0)
 
 /* just like mkframe, but also reserves space for a struct     */
 /* with the given tag at the bottom of the nondet stack frame  */
-#define	mkpragmaframe(prednm, numslots, structname, redoip)	\
-			do {					\
-				reg	Word	*prevfr;	\
-				reg	Word	*succfr;	\
-								\
-				prevfr = MR_maxfr;		\
-				succfr = MR_curfr;		\
-				MR_maxfr += (NONDET_FIXED_SIZE + numslots \
+#define	mkpragmaframe(prednm, numslots, structname, redoip)		\
+			do {						\
+				reg	Word	*prevfr;		\
+				reg	Word	*succfr;		\
+									\
+				prevfr = MR_maxfr;			\
+				succfr = MR_curfr;			\
+				MR_maxfr += (MR_NONDET_FIXED_SIZE + numslots \
 					+ sizeof(struct structname));	\
-				MR_curfr = MR_maxfr;		\
-				curredoip = redoip;		\
-				curprevfr = prevfr;		\
-				cursuccip = MR_succip;		\
-				cursuccfr = succfr;		\
-				curredofr = MR_curfr;		\
-				mkframe_save_prednm(prednm);	\
-				debugmkframe();			\
-				nondstack_overflow_check();	\
+				MR_curfr = MR_maxfr;			\
+				MR_redoip_slot(MR_curfr) = redoip;	\
+				MR_prevfr_slot(MR_curfr) = prevfr;	\
+				MR_succip_slot(MR_curfr) = MR_succip;	\
+				MR_succfr_slot(MR_curfr) = succfr;	\
+				MR_redofr_slot(MR_curfr) = MR_curfr;	\
+				mkframe_save_prednm(prednm);		\
+				debugmkframe();				\
+				nondstack_overflow_check();		\
 			} while (0)
 
 #define	mktempframe(redoip)						\
-			do {					\
-				reg	Word	*prevfr;	\
-				reg	Word	*succfr;	\
-								\
-				prevfr = MR_maxfr;		\
-				succfr = MR_curfr;		\
-				MR_maxfr += NONDET_TEMP_SIZE;	\
-				bt_prevfr(MR_maxfr) = prevfr;	\
-				bt_redoip(MR_maxfr) = redoip;	\
-				bt_redofr(MR_maxfr) = MR_curfr;	\
-				nondstack_overflow_check();	\
-			} while (0)
-
-#define	modframe(redoip)					\
-			do {					\
-				curredoip = redoip;		\
-				debugmodframe();		\
-			} while (0)
-
-#define	succeed()	do {					\
-				reg	Word	*childfr;	\
-								\
-				debugsucceed();			\
-				childfr = MR_curfr;		\
-				MR_curfr = cursuccfr;		\
-				GOTO(bt_succip(childfr));	\
-			} while (0)
-
-#define	succeed_discard()					\
-			do {					\
-				reg	Word	*childfr;	\
-								\
-				debugsucceeddiscard();		\
-				childfr = MR_curfr;		\
-				MR_maxfr = curprevfr;		\
-				MR_curfr = cursuccfr;		\
-				GOTO(bt_succip(childfr));	\
+			do {						\
+				reg	Word	*prevfr;		\
+				reg	Word	*succfr;		\
+									\
+				prevfr = MR_maxfr;			\
+				succfr = MR_curfr;			\
+				MR_maxfr += MR_NONDET_TEMP_SIZE;	\
+				MR_prevfr_slot(MR_maxfr) = prevfr;	\
+				MR_redoip_slot(MR_maxfr) = redoip;	\
+				MR_redofr_slot(MR_maxfr) = MR_curfr;	\
+				nondstack_overflow_check();		\
+			} while (0)
+
+#define	mkdettempframe(redoip)						\
+			do {						\
+				reg	Word	*prevfr;		\
+				reg	Word	*succfr;		\
+									\
+				prevfr = MR_maxfr;			\
+				succfr = MR_curfr;			\
+				MR_maxfr += MR_DET_TEMP_SIZE;		\
+				MR_prevfr_slot(MR_maxfr) = prevfr;	\
+				MR_redoip_slot(MR_maxfr) = redoip;	\
+				MR_redofr_slot(MR_maxfr) = MR_curfr;	\
+				MR_detfr_slot(MR_maxfr)  = MR_sp;	\
+				nondstack_overflow_check();		\
+			} while (0)
+
+#define	succeed()	do {						\
+				reg	Word	*childfr;		\
+									\
+				debugsucceed();				\
+				childfr = MR_curfr;			\
+				MR_curfr = MR_succfr_slot(childfr);	\
+				GOTO(MR_succip_slot(childfr));		\
+			} while (0)
+
+#define	succeed_discard()						\
+			do {						\
+				reg	Word	*childfr;		\
+									\
+				debugsucceeddiscard();			\
+				childfr = MR_curfr;			\
+				MR_maxfr = MR_prevfr_slot(childfr);	\
+				MR_curfr = MR_succfr_slot(childfr);	\
+				GOTO(MR_succip_slot(childfr));		\
 			} while (0)
 
 
-#define	fail()		do {					\
-				debugfail();			\
-				MR_maxfr = bt_prevfr(MR_maxfr);	\
-				nondstack_underflow_check();	\
-				MR_curfr = bt_redofr(MR_maxfr);	\
-				GOTO(bt_redoip(MR_maxfr));	\
+#define	fail()		do {						\
+				debugfail();				\
+				MR_maxfr = MR_prevfr_slot(MR_maxfr);	\
+				nondstack_underflow_check();		\
+				MR_curfr = MR_redofr_slot(MR_maxfr);	\
+				GOTO(MR_redoip_slot(MR_maxfr));		\
 			} while (0)
 
 
-#define	redo()		do {					\
-				debugredo();			\
-				MR_curfr = bt_redofr(MR_maxfr);	\
-				GOTO(bt_redoip(MR_maxfr));	\
+#define	redo()		do {						\
+				debugredo();				\
+				MR_curfr = MR_redofr_slot(MR_maxfr);	\
+				GOTO(MR_redoip_slot(MR_maxfr));		\
 			} while (0)
 
 #endif /* not MERCURY_STACKS_H */
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 scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/general
Index: tests/general/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/general/Mmakefile,v
retrieving revision 1.18
diff -u -u -r1.18 Mmakefile
--- Mmakefile	1998/07/27 11:09:28	1.18
+++ Mmakefile	1998/07/27 11:30:43
@@ -59,10 +59,9 @@
 		univ \
 		unreachable 
 
-# space.m does not work, due to an unfixed bug in code generation.
 # dnf.m does not work in non-gc grades, because it uses `pragma memo'
 # (i.e. tabling) and tabling is not yet implemented for non-gc grades.
-NOT_WORKING =	space dnf
+NOT_WORKING =	dnf
 
 # mode_inf and mode_inf_bug need to be compiled with `--infer-all'.
 MCFLAGS-mode_inf = --infer-all
Index: tests/general/space.exp
===================================================================
RCS file: space.exp
diff -N space.exp
--- /tmp/cvs12558Baa	Mon Jul 27 21:34:46 1998
+++ /dev/null	Wed May 28 10:49:58 1997
@@ -1,30 +0,0 @@
-a2 d3 f3
-a2 c3 e3
-f2 a#2 d3
-e2 g2 c3
-f2 a2 d3
-a2 c3 e3
-a2 d3 f3
-a2 c3 e3
-g#2 c3 f3
-c3 e3 g3
-c3 f3 a3
-d3 g3 a#3
-c3 f3 a3
-d3 g3 a#3
-e3 g3 c4
-d3 f3 a#3
-c3 e3 a3
-d3 f3 a#3
-e3 a3 c4
-f3 a#3 d4
-e3 a3 c4
-f3 a#3 d4
-e3 g3 c4
-d3 f3 a#3
-c3 f3 a3
-a#2 d3 g3
-a2 c3 f3
-g2 c3 e3
-g2 a#2 d3
-f2 a2 c3
Index: tests/general/space.m
===================================================================
RCS file: space.m
diff -N space.m
--- /tmp/cvs12558Caa	Mon Jul 27 21:34:47 1998
+++ /dev/null	Wed May 28 10:49:58 1997
@@ -1,752 +0,0 @@
<moved to tests/hard_coded>
cvs diff: Diffing tests/hard_coded
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.37
diff -u -u -r1.37 Mmakefile
--- Mmakefile	1998/07/27 11:09:32	1.37
+++ Mmakefile	1998/07/27 11:30:48
@@ -15,10 +15,13 @@
 	cc_nondet_disj \
 	cc_and_non_cc_test \
 	common_type_cast \
+	complex_failure \
 	construct \
 	curry \
 	curry2 \
 	cut_test \
+ 	cycles \
+ 	cycles2 \
 	deep_copy_bug \
 	det_in_semidet_cntxt \
 	division_test \
@@ -76,6 +79,7 @@
 	reverse_arith \
 	rnd \
 	rtc_bug \
+	space \
 	string_alignment \
 	string_loop \
 	test_imported_no_tag \
@@ -83,10 +87,6 @@
 	write \
 	write_reg1
 
-# Not working:
-# 	cycles - loops when compiled in a non-GC grade with --deforestation.
-# 	cycles2 - loops when compiled in a non-GC grade.
-
 # The following is required to make the test cases
 #	nested, nested2, and nested3
 # work reliabily with parallel makes -- without this they occaisionally fail.
Index: tests/hard_coded/complex_failure.exp
===================================================================
RCS file: complex_failure.exp
diff -N complex_failure.exp
--- /dev/null	Wed May 28 10:49:58 1997
+++ complex_failure.exp	Sun Jul 26 17:47:54 1998
@@ -0,0 +1,3 @@
+[1600, 1601, 1800, 1801, 1900, 1901, 6600, 6601]
+[2500, 2501, 2800, 2801, 2900, 2901, 6900, 6901]
+[3500, 3501, 3800, 3801]
Index: tests/hard_coded/complex_failure.m
===================================================================
RCS file: complex_failure.m
diff -N complex_failure.m
--- /dev/null	Wed May 28 10:49:58 1997
+++ complex_failure.m	Fri Jul 24 20:56:18 1998
@@ -0,0 +1,130 @@
+% This test case exercises the code generator's handling of if-then-elses
+% whose conditions include nondet disjunctions, looking for problems caused
+% by the disjunction's clobbering some of the same redoip/redofr slots used
+% for the soft cut in the if-then-else.
+
+% Note that NU-Prolog cannot execute this test case correctly. With -> ;
+% notation, NU-Prolog does a hard neck cut, which is not Mercury's desired
+% semantics; with the if-then-else notation, it delays the conditions
+% since they are not ground.
+
+:- module complex_failure.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module std_util, list, int.
+
+main -->
+	{ solutions(p1, Xs1) },
+	print_list(Xs1),
+	{ solutions(p2, Xs2) },
+	print_list(Xs2),
+	{ solutions(p3, Xs3) },
+	print_list(Xs3).
+
+:- pred p1(int::out) is nondet.
+
+p1(X) :-
+	p(1, X).
+
+:- pred p2(int::out) is nondet.
+
+p2(X) :-
+	p(2, X).
+
+:- pred p3(int::out) is nondet.
+
+p3(X) :-
+	p(3, X).
+
+:- pred p(int::in, int::out) is nondet.
+
+p(A, X) :-
+	% The first if-then-else can hijack the redoip/redofr slots
+	% of p's frame.
+	(
+		( q(A, B) ; r(A, B) )
+	->
+		C is B * 10
+		% s(B, C)
+	;
+		C is A * 10
+		% s(A, C)
+	),
+	% The second if-then-else cannot hijack the redoip/redofr slots
+	% of p's frame, since this may not be (and usually won't be)
+	% on top when execution gets here.
+	(
+		( q(C, D) ; r(C, D) )
+	->
+		s(D, X)
+	;
+		s(C, X)
+	).
+
+:- pred q(int::in, int::out) is nondet.
+
+q(1, 15).
+q(1, 16).
+q(2, 25).
+q(2, 26).
+q(3, 35).
+
+q(150, 660).
+q(161, 661).
+q(281, 662).
+
+:- pred r(int::in, int::out) is nondet.
+
+r(1, 18).
+r(1, 19).
+r(2, 28).
+r(2, 29).
+r(3, 38).
+r(260, 690).
+r(370, 698).
+
+:- pred s(int::in, int::out) is nondet.
+
+s(F, G) :-
+	F < 695,
+	(
+		G is 10 * F
+	;
+		G is 10 * F + 1
+	).
+
+:- pred print_list(list(int), io__state, io__state).
+:- mode print_list(in, di, uo) is det.
+
+print_list(Xs) -->
+	(
+		{ Xs = [] }
+	->
+		io__write_string("[]\n")
+	;
+		io__write_string("["),
+		print_list_2(Xs),
+		io__write_string("]\n")
+	).
+
+:- pred print_list_2(list(int), io__state, io__state).
+:- mode print_list_2(in, di, uo) is det.
+
+print_list_2([]) --> [].
+print_list_2([X|Xs]) --> 
+	io__write_int(X),
+	(
+		{ Xs = [] }
+	->
+		[]
+	;
+		io__write_string(", "),
+		print_list_2(Xs)
+	).
Index: tests/hard_coded/cycles2.exp
===================================================================
RCS file: cycles2.exp
diff -N cycles2.exp
--- /dev/null	Wed May 28 10:49:58 1997
+++ cycles2.exp	Mon Jul 27 11:11:48 1998
@@ -0,0 +1 @@
+[[a, d, a]]
Index: tests/hard_coded/space.exp
===================================================================
RCS file: space.exp
diff -N space.exp
--- /dev/null	Wed May 28 10:49:58 1997
+++ space.exp	Wed Nov 12 15:41:03 1997
@@ -0,0 +1,30 @@
+a2 d3 f3
+a2 c3 e3
+f2 a#2 d3
+e2 g2 c3
+f2 a2 d3
+a2 c3 e3
+a2 d3 f3
+a2 c3 e3
+g#2 c3 f3
+c3 e3 g3
+c3 f3 a3
+d3 g3 a#3
+c3 f3 a3
+d3 g3 a#3
+e3 g3 c4
+d3 f3 a#3
+c3 e3 a3
+d3 f3 a#3
+e3 a3 c4
+f3 a#3 d4
+e3 a3 c4
+f3 a#3 d4
+e3 g3 c4
+d3 f3 a#3
+c3 f3 a3
+a#2 d3 g3
+a2 c3 f3
+g2 c3 e3
+g2 a#2 d3
+f2 a2 c3
Index: tests/hard_coded/space.m
===================================================================
RCS file: space.m
diff -N space.m
--- /dev/null	Wed May 28 10:49:58 1997
+++ space.m	Wed Nov 12 15:40:57 1997
<what it was in tests/general>
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools



More information about the developers mailing list