diff: bug fix for dense_switch.m

Fergus Henderson fjh at cs.mu.oz.au
Tue May 20 02:58:35 AEST 1997


Hi,

Zoltan and/or Tom, could you please review this?

compiler/dense_switch.m:
	Fix a bug introduced by Zoltan's changes to delay flushing
	of variables needed on backtracking.
	The bug was that the final code_info after a nondet
	dense_switch had not unset the top failure continuation.
	This caused the code generator to generate incorrect C code for
	the code following the dense switch: the generated C code
	clobbered the topmost redoip, rather than using a new temp frame.
	The fix was to ensure that we use the code_info from the
	end of one of the switch branches (for which we will have called
	code_info__unset_failure_cont from code_info__branch_end)
	rather than using the initial code_info and just resetting
	the live variables.

compiler/code_gen.m:
compiler/code_info.m:
compiler/disj_info.m:
compiler/ite_gen.m:
	Various minor improvements to the comments.

tests/general/space.m:
	The regression test for the above-mentioned bug,
	from Tom's original bug report.

cvs diff: Diffing .
Index: code_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/code_gen.m,v
retrieving revision 1.24
diff -u -r1.24 code_gen.m
--- code_gen.m	1997/05/05 11:16:40	1.24
+++ code_gen.m	1997/05/19 05:03:18
@@ -906,7 +906,6 @@
 		Code) -->
 		% This code is a cut-down version of the code for semidet
 		% if-then-elses.
-		% XXX It does not save or restore tickets
 
 	code_info__make_known_failure_cont(ResumeVars, ResumeLocs, no,
 		no, _, ModContCode),
Index: code_info.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/code_info.m,v
retrieving revision 1.199
diff -u -r1.199 code_info.m
--- code_info.m	1997/04/25 09:14:27	1.199
+++ code_info.m	1997/05/19 07:53:44
@@ -1194,8 +1194,8 @@
 			;
 				{ TempFrameCode = node([
 					assign(redoip(lval(maxfr)),
-						const(code_addr_const(RedoAddr)))
-						- "Set failure continuation"
+					    const(code_addr_const(RedoAddr)))
+				- "Set failure continuation on temp frame"
 				]) }
 			),
 			{ HaveTempFrame = yes }
@@ -1348,7 +1348,7 @@
 			ResetCode = node([
 				assign(redoip(lval(maxfr)),
 					const(code_addr_const(RedoAddress)))
-					- "restore failure cont"
+					- "restore known failure cont"
 			])
 		}
 	),
Index: dense_switch.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/dense_switch.m,v
retrieving revision 1.23
diff -u -r1.23 dense_switch.m
--- dense_switch.m	1997/02/19 05:30:00	1.23
+++ dense_switch.m	1997/05/19 09:52:20
@@ -162,17 +162,19 @@
 	),
 		% Now generate the jump table and the cases
 	dense_switch__generate_cases(Cases, StartVal, EndVal, CodeModel,
-			StoreMap, EndLabel, Labels, CasesCode, no, MLiveness),
-		% We keep track of what variables are supposed to be
-		% live at the end of cases. We have to do this explicitly
-		% because generating a `fail' slot last would yield the
-		% wrong liveness.
+			StoreMap, EndLabel, Labels, CasesCode, no,
+			MaybeFinalCodeInfo),
+		% We keep track of the code_info at the end of one of
+		% the non-fail cases.  We have to do this because 
+		% generating a `fail' slot last would yield the
+		% wrong liveness and would not unset the failure cont
+		% for a nondet switch.
 	(
-		{ MLiveness = yes(Liveness) }
+		{ MaybeFinalCodeInfo = yes(FinalCodeInfo) }
 	->
-		code_info__set_forward_live_vars(Liveness)
+		code_info__slap_code_info(FinalCodeInfo)
 	;
-		{ error("dense_switch__generate: no liveness!") }
+		{ error("dense_switch__generate: no final code_info") }
 	),
 	{ DoJump = node([
 		computed_goto(Index, Labels)
@@ -183,22 +185,22 @@
 
 :- pred dense_switch__generate_cases(cases_list, int, int,
 	code_model, store_map, label, list(label), code_tree, 
-	maybe(liveness_info), maybe(liveness_info), code_info, code_info).
+	maybe(code_info), maybe(code_info), code_info, code_info).
 :- mode dense_switch__generate_cases(in, in, in, in, in, in, out, out,
 	in, out, in, out) is det.
 
 dense_switch__generate_cases(Cases0, NextVal, EndVal, CodeModel, StoreMap,
-		EndLabel, Labels, Code, Liveness0, Liveness) -->
+		EndLabel, Labels, Code, MaybeCodeInfo0, MaybeCodeInfo) -->
 	(
 		{ NextVal > EndVal }
 	->
 		{ Code = node([ label(EndLabel) - "End of dense switch" ]) },
 		{ Labels = [] },
-		{ Liveness = Liveness0 }
+		{ MaybeCodeInfo = MaybeCodeInfo0 }
 	;
 		code_info__get_next_label(ThisLabel),
 		dense_switch__generate_case(Cases0, NextVal, CodeModel,
-			StoreMap, Cases1, ThisCode, Comment, NewLiveness),
+			StoreMap, Cases1, ThisCode, Comment, MaybeNewCodeInfo),
 		{ ThisCaseCode = tree(
 			node([ label(ThisLabel) - Comment ]),
 			tree(	ThisCode,
@@ -206,13 +208,13 @@
 					- "branch to end of dense switch" ])
 			)
 		) },
-		{ dense_switch__merge_maybe_liveness(Liveness0, NewLiveness,
-				Liveness1) },
+		{ dense_switch__merge_maybe_code_info(MaybeCodeInfo0,
+				MaybeNewCodeInfo, MaybeCodeInfo1) },
 			% generate the rest of the cases.
 		{ NextVal1 is NextVal + 1 },
 		dense_switch__generate_cases(Cases1, NextVal1, EndVal,
 			CodeModel, StoreMap, EndLabel, Labels1, OtherCasesCode,
-			Liveness1, Liveness),
+			MaybeCodeInfo1, MaybeCodeInfo),
 		{ Labels = [ThisLabel | Labels1] },
 		{ Code = tree(ThisCaseCode, OtherCasesCode) }
 	).
@@ -220,47 +222,47 @@
 %---------------------------------------------------------------------------%
 
 :- pred dense_switch__generate_case(cases_list, int, code_model, store_map,
-		cases_list, code_tree, string,
-			maybe(liveness_info), code_info, code_info).
-:- mode dense_switch__generate_case(in, in, in, in, out, out, out, out, in, out)
-	is det.
+		cases_list, code_tree, string, maybe(code_info),
+		code_info, code_info).
+:- mode dense_switch__generate_case(in, in, in, in, out, out, out, out,
+		in, out) is det.
 
 dense_switch__generate_case(Cases0, NextVal, CodeModel, StoreMap, Cases,
-		Code, Comment, ML) -->
+		Code, Comment, MaybeCodeInfo) -->
 	(
 		{ Cases0 = [Case | Cases1] },
 		{ Case = case(_, int_constant(NextVal), _, Goal) }
 	->
+		{ Comment = "case of dense switch" },
 		% We need to save the expression cache, etc.,
 		% and restore them when we've finished
-		{ Comment = "case of dense switch" },
-		code_info__grab_code_info(CodeInfo),
+		code_info__grab_code_info(CodeInfoAtStart),
 		code_gen__generate_goal(CodeModel, Goal, GoalCode),
 		code_info__generate_branch_end(CodeModel, StoreMap, SaveCode),
 		{ Code = tree(GoalCode, SaveCode) },
-		code_info__get_forward_live_vars(L),
-		code_info__slap_code_info(CodeInfo),
+		code_info__grab_code_info(CodeInfoAtEnd),
+		code_info__slap_code_info(CodeInfoAtStart),
 		{ Cases = Cases1 },
-		{ ML = yes(L) }
+		{ MaybeCodeInfo = yes(CodeInfoAtEnd) }
 	;
 		% This case didn't occur in the original case list - just
 		% generate a `fail' for it.
 		{ Comment = "compiler-introduced `fail' case of dense switch" },
 		code_info__generate_failure(Code),
 		{ Cases = Cases0 },
-		{ ML = no }
+		{ MaybeCodeInfo = no }
 	).
 
-:- pred dense_switch__merge_maybe_liveness(maybe(liveness_info),
-				maybe(liveness_info), maybe(liveness_info)).
-:- mode dense_switch__merge_maybe_liveness(in, in, out) is det.
+:- pred dense_switch__merge_maybe_code_info(maybe(code_info),
+				maybe(code_info), maybe(code_info)).
+:- mode dense_switch__merge_maybe_code_info(in, in, out) is det.
 
-dense_switch__merge_maybe_liveness(L0, L1, L) :-
+dense_switch__merge_maybe_code_info(CodeInfo0, CodeInfo1, CodeInfo) :-
 	(
-		L0 = no
+		CodeInfo0 = no
 	->
-		L = L1
+		CodeInfo = CodeInfo1
 	;
-		L = L0
+		CodeInfo = CodeInfo0
 	).
 
Index: disj_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/disj_gen.m,v
retrieving revision 1.53
diff -u -r1.53 disj_gen.m
--- disj_gen.m	1997/02/23 06:06:07	1.53
+++ disj_gen.m	1997/05/19 08:09:06
@@ -104,7 +104,8 @@
 	% For a det disj, this goal will be det,
 	% and may be followed by other goals.
 	%
-	% XXX We ought not to restore anything in the first disjunct.
+	% XXX For efficiency, we ought not to restore anything in the
+	% first disjunct.
 
 disj_gen__generate_pruned_disjuncts([], _, _, _, _, _, _, _, _) -->
 	{ error("Empty pruned disjunction!") }.
@@ -250,7 +251,7 @@
 		MaybeHpSlot, MaybeTicketSlot, no, GoalsCode),
 
 		% since we don't know which disjunct we have come from
-		% we must set the current failure continuation to unkown.
+		% we must set the current failure continuation to unknown.
 
 	code_info__unset_failure_cont(FlushResumeVarsCode),
 	code_info__remake_with_store_map(StoreMap),
@@ -261,7 +262,8 @@
 
 %---------------------------------------------------------------------------%
 
-	% XXX We ought not to restore anything in the first disjunct.
+	% XXX For efficiency, we ought not to restore anything in the
+	% first disjunct.
 
 :- pred disj_gen__generate_non_disjuncts(list(hlds_goal), store_map, label,
 	bool, maybe(lval), maybe(lval), bool, code_tree, code_info, code_info).
@@ -361,7 +363,7 @@
 		code_info__generate_branch_end(model_non, StoreMap, SaveCode),
 
 		{ EndCode = node([
-			label(EndLabel) - "End of pruned disj"
+			label(EndLabel) - "End of nondet disj"
 		]) },
 		{ Code = tree(RestoreHPCode,
 			 tree(RestorePopTicketCode,
Index: ite_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/ite_gen.m,v
retrieving revision 1.41
diff -u -r1.41 ite_gen.m
--- ite_gen.m	1997/02/23 06:06:43	1.41
+++ ite_gen.m	1997/05/19 09:15:46
@@ -212,7 +212,7 @@
 
 	code_info__grab_code_info(CodeInfo),
 
-		% Generate the condition es either a semi-deterministic
+		% Generate the condition as either a semi-deterministic
 		% or as a non-deterministic goal (the failure continuation
 		% must be set up the same way)
 	code_info__push_resume_point_vars(ResumeVars),
@@ -223,6 +223,10 @@
 	( { MaybeMaxfrLval = yes(MaxfrLval) } ->
 		code_info__do_soft_cut(MaxfrLval, SoftCutCode),
 		code_info__unset_failure_cont(FlushCode)
+			% XXX why call unset_failure_cont here?
+			% We're going to call it from branch_end at the
+			% end of the `then' anyway, so is this
+			% one really necessary?
 	;
 		{ SoftCutCode = empty },
 		{ FlushCode = empty }
cvs diff: Diffing notes

-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list