for review: the second batch of trace ports

Zoltan Somogyi zs at cs.mu.oz.au
Sat Oct 11 17:48:09 AEST 1997


Estimated hours taken: 5

When generating code that raises trace events at runtime, trace not just
procedure calls, exits and failures, but also entries to switch arms,
disjunction arms and to the then and else parts of if-then-elses.
These new trace ports are exactly what is needed to let the trace analyzer
figure out what path execution took inside a procedure. (This includes
knowing at what point forward execution resumes after backtracking.)
The new ports correspond to the UNIFY port in the Opium debugger, which
signified entry to a clause.

These new ports complete the set of ports required for generating traces
whose information content is approximately equivalent to Opium (i.e. as
close to Opium functionality as we can get in Mercury).

compiler/trace.m:
	Add code to handle the new ports.

compiler/hlds_goal.m:
	Add an extra slot to each hlds_goal_info structure. This slot
	holds information about the position of the goal within the
	procedure, in the form of a description of the path from the
	root of the main goal to this goal. This info is included in
	the new trace ports.  It is likely that this info will also be
	used by optimizations (such as loop invariant removal) to be
	implemented later.

compiler/goal_path.m:
	A new module whose job it is to fill the new goal_info slot;
	later it may also contain code to e.g. check whether one goal
	is before, after, or parallel to another.

compiler/hlds_out.m:
	Include the new slot in HLDS dumps.

compiler/mercury_compile.m:
	Invoke code in goal_path.m to fill in the new slot just before
	code generation when generating traces.

compiler/dense_switch.m:
compiler/disj_gen.m:
compiler/ite_gen.m:
compiler/string_switch.m:
compiler/switch_gen.m:
compiler/tag_switch.m:
	Emit code for invoking the new trace ports.

runtime/mercury_trace.c:
runtime/mercury_trace.h:
	Implement the new ports.

Zoltan.

Index: compiler/dense_switch.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dense_switch.m,v
retrieving revision 1.28
diff -u -r1.28 dense_switch.m
--- dense_switch.m	1997/08/22 13:54:43	1.28
+++ dense_switch.m	1997/10/11 08:18:56
@@ -49,7 +49,7 @@
 
 :- implementation.
 
-:- import_module hlds_module, hlds_goal, hlds_data, code_gen.
+:- import_module hlds_module, hlds_goal, hlds_data, code_gen, trace.
 :- import_module char, map, tree, int, std_util, require, list.
 
 dense_switch__is_dense_switch(CaseVar, TaggedCases, CanFail0, ReqDensity,
@@ -237,9 +237,22 @@
 		% We need to save the expression cache, etc.,
 		% and restore them when we've finished
 		code_info__grab_code_info(CodeInfoAtStart),
+		code_info__get_maybe_trace_info(MaybeTraceInfo),
+		( { MaybeTraceInfo = yes(TraceInfo) } ->
+			{ Goal = _ - GoalInfo },
+			{ goal_info_get_goal_path(GoalInfo, Path) },
+			trace__generate_event_code(switch(Path), TraceInfo,
+				TraceCode)
+		;
+			{ TraceCode = empty }
+		),
 		code_gen__generate_goal(CodeModel, Goal, GoalCode),
 		code_info__generate_branch_end(CodeModel, StoreMap, SaveCode),
-		{ Code = tree(GoalCode, SaveCode) },
+		{ Code =
+			tree(TraceCode,
+			tree(GoalCode,
+			     SaveCode))
+		},
 		code_info__grab_code_info(CodeInfoAtEnd),
 		code_info__slap_code_info(CodeInfoAtStart),
 		{ Cases = Cases1 },
Index: compiler/disj_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/disj_gen.m,v
retrieving revision 1.58
diff -u -r1.58 disj_gen.m
--- disj_gen.m	1997/08/24 01:29:37	1.58
+++ disj_gen.m	1997/10/11 06:51:12
@@ -38,7 +38,7 @@
 
 :- implementation.
 
-:- import_module hlds_data, code_gen, code_util, options, globals.
+:- import_module hlds_data, code_gen, code_util, trace, options, globals.
 :- import_module bool, set, tree, list, map, std_util, require.
 
 %---------------------------------------------------------------------------%
@@ -166,6 +166,14 @@
 		;
 			error("pruned disj non-last goal is not semidet")
 		},
+		code_info__get_maybe_trace_info(MaybeTraceInfo),
+		( { MaybeTraceInfo = yes(TraceInfo) } ->
+			{ goal_info_get_goal_path(GoalInfo, Path) },
+			trace__generate_event_code(disj(Path), TraceInfo,
+				TraceCode)
+		;
+			{ TraceCode = empty }
+		),
 		code_gen__generate_goal(CodeModel, Goal, GoalCode),
 		code_info__generate_branch_end(CodeModel, StoreMap, SaveCode),
 
@@ -186,11 +194,13 @@
 			 tree(RestoreHPCode,
 			 tree(SaveHPCode,
 			 tree(RestoreTicketCode,
+			 tree(TraceCode,
 			 tree(GoalCode,
 			 tree(SaveCode,
 			 tree(BranchCode,
 			 tree(RestoreContCode,
-			      RestCode)))))))) }
+			      RestCode)))))))))
+		}
 	;
 		% Emit code for the last disjunct
 
@@ -203,6 +213,14 @@
 			undo, RestorePopTicketCode),
 
 			% Generate the goal
+		code_info__get_maybe_trace_info(MaybeTraceInfo),
+		( { MaybeTraceInfo = yes(TraceInfo) } ->
+			{ goal_info_get_goal_path(GoalInfo0, Path) },
+			trace__generate_event_code(disj(Path), TraceInfo,
+				TraceCode)
+		;
+			{ TraceCode = empty }
+		),
 		code_gen__generate_goal(CodeModel, Goal0, GoalCode),
 		code_info__generate_branch_end(CodeModel, StoreMap, SaveCode),
 
@@ -211,9 +229,11 @@
 		]) },
 		{ Code = tree(RestoreHPCode,
 			 tree(RestorePopTicketCode,
+			 tree(TraceCode,
 			 tree(GoalCode,
 			 tree(SaveCode,
-			      EndCode)))) }
+			      EndCode)))))
+		}
 	).
 
 %---------------------------------------------------------------------------%
@@ -308,6 +328,15 @@
 
 		code_info__grab_code_info(CodeInfo),
 
+		code_info__get_maybe_trace_info(MaybeTraceInfo),
+		( { MaybeTraceInfo = yes(TraceInfo) } ->
+			{ goal_info_get_goal_path(GoalInfo, Path) },
+			trace__generate_event_code(disj(Path), TraceInfo,
+				TraceCode)
+		;
+			{ TraceCode = empty }
+		),
+
 		code_gen__generate_goal(model_non, Goal, GoalCode),
 		code_info__generate_branch_end(model_non, StoreMap, SaveCode),
 
@@ -334,12 +363,14 @@
 		{ Code = tree(ModContCode, 
 			 tree(RestoreHPCode,
 			 tree(RestoreTicketCode,
+			 tree(TraceCode,
 			 tree(GoalCode,
 			 tree(SaveCode,
 			 tree(FlushResumeVarsCode,
 			 tree(BranchCode,
 			 tree(RestoreContCode,
-			      RestCode)))))))) }
+			      RestCode)))))))))
+		}
 	;
 		% Emit code for the last disjunct
 
@@ -357,6 +388,15 @@
 		code_info__maybe_reset_and_discard_ticket(MaybeTicketSlot,
 			undo, RestorePopTicketCode),
 
+		code_info__get_maybe_trace_info(MaybeTraceInfo),
+		( { MaybeTraceInfo = yes(TraceInfo) } ->
+			{ goal_info_get_goal_path(GoalInfo0, Path) },
+			trace__generate_event_code(disj(Path), TraceInfo,
+				TraceCode)
+		;
+			{ TraceCode = empty }
+		),
+
 		code_gen__generate_goal(model_non, Goal0, GoalCode),
 		code_info__generate_branch_end(model_non, StoreMap, SaveCode),
 
@@ -365,9 +405,11 @@
 		]) },
 		{ Code = tree(RestoreHPCode,
 			 tree(RestorePopTicketCode,
+			 tree(TraceCode,
 			 tree(GoalCode,
 			 tree(SaveCode,
-			      EndCode)))) }
+			      EndCode)))))
+		}
 	).
 
 %---------------------------------------------------------------------------%
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.41
diff -u -r1.41 hlds_goal.m
--- hlds_goal.m	1997/10/09 09:38:38	1.41
+++ hlds_goal.m	1997/10/11 07:24:38
@@ -378,6 +378,25 @@
 			;	orig_and_stack
 			;	stack_and_orig.
 
+	% We can think of the goal that defines a procedure to be a tree,
+	% whose leaves are primitive goals and whose interior nodes are
+	% compound goals. These two types describe the position of a goal
+	% in this tree. The first says which branch to take at an interior
+	% node (the integer counts start at one). The second gives the
+	% sequence of steps from the root to the given goal *in reverse order*,
+	% so that the step closest to the root is last.
+
+:- type goal_path_step	--->	conj(int)
+			;	disj(int)
+			;	switch(int)
+			;	ite_cond
+			;	ite_then
+			;	ite_else
+			;	neg
+			;	exist.
+
+:- type goal_path == list(goal_path_step).
+
 :- implementation.
 
 	% NB. Don't forget to check goal_util__name_apart_goalinfo
@@ -437,12 +456,16 @@
 				% this goal, which optimisers may wish
 				% to know about.
 
-		resume_point
+		resume_point,
 				% If this goal establishes a resumption point,
 				% state what variables need to be saved for
 				% that resumption point, and which entry
 				% labels of the resumption point will be
 				% needed. (See compiler/notes/allocation.html)
+
+		goal_path
+				% The path to this goal from the root in
+				% reverse order.
 	).
 
 get_pragma_c_var_names(MaybeVarNames, VarNames) :-
@@ -577,6 +600,12 @@
 	hlds_goal_info).
 :- mode goal_info_set_resume_point(in, in, out) is det.
 
+:- pred goal_info_get_goal_path(hlds_goal_info, goal_path).
+:- mode goal_info_get_goal_path(in, out) is det.
+
+:- pred goal_info_set_goal_path(hlds_goal_info, goal_path, hlds_goal_info).
+:- mode goal_info_set_goal_path(in, in, out) is det.
+
 :- pred goal_set_follow_vars(hlds_goal, maybe(follow_vars), hlds_goal).
 :- mode goal_set_follow_vars(in, in, out) is det.
 
@@ -662,7 +691,7 @@
 	set__init(Features),
 	GoalInfo = goal_info(PreBirths, PostBirths, PreDeaths, PostDeaths,
 		Detism, InstMapDelta, Context, NonLocals, no, Features,
-		no_resume_point).
+		no_resume_point, []).
 
 goal_info_init(NonLocals, InstMapDelta, Detism, GoalInfo) :-
 	goal_info_init(GoalInfo0),
@@ -671,37 +700,40 @@
 	goal_info_set_determinism(GoalInfo2, Detism, GoalInfo).
 
 goal_info_get_pre_births(GoalInfo, PreBirths) :-
-	GoalInfo = goal_info(PreBirths, _, _, _, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(PreBirths, _, _, _, _, _, _, _, _, _, _, _).
 
 goal_info_get_post_births(GoalInfo, PostBirths) :-
-	GoalInfo = goal_info(_, PostBirths, _, _, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, PostBirths, _, _, _, _, _, _, _, _, _, _).
 
 goal_info_get_pre_deaths(GoalInfo, PreDeaths) :-
-	GoalInfo = goal_info(_, _, PreDeaths, _, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, PreDeaths, _, _, _, _, _, _, _, _, _).
 
 goal_info_get_post_deaths(GoalInfo, PostDeaths) :-
-	GoalInfo = goal_info(_, _, _, PostDeaths, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, PostDeaths, _, _, _, _, _, _, _, _).
 
 goal_info_get_determinism(GoalInfo, Determinism) :-
-	GoalInfo = goal_info(_, _, _, _, Determinism, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, Determinism, _, _, _, _, _, _, _).
 
 goal_info_get_instmap_delta(GoalInfo, InstMapDelta) :-
-	GoalInfo = goal_info(_, _, _, _, _, InstMapDelta, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, InstMapDelta, _, _, _, _, _, _).
 
 goal_info_get_context(GoalInfo, Context) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, Context, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, Context, _, _, _, _, _).
 
 goal_info_get_nonlocals(GoalInfo, NonLocals) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, NonLocals, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, NonLocals, _, _, _, _).
 
 goal_info_get_follow_vars(GoalInfo, MaybeFollowVars) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, MaybeFollowVars, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, MaybeFollowVars, _, _, _).
 
 goal_info_get_features(GoalInfo, Features) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, Features, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, Features, _, _).
 
 goal_info_get_resume_point(GoalInfo, ResumePoint) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, ResumePoint).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, ResumePoint, _).
+
+goal_info_get_goal_path(GoalInfo, GoalPath) :-
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, _, GoalPath).
 
 % :- type hlds_goal_info
 % 	--->	goal_info(
@@ -715,52 +747,57 @@
 % 		H	set(var),	% the non-local vars in the goal
 % 		I	maybe(follow_vars),
 % 		J	set(goal_feature),
-%		K	resume_point
+%		K	resume_point,
+%		L	goal_path
 % 	).
 
 goal_info_set_pre_births(GoalInfo0, PreBirths, GoalInfo) :-
-	GoalInfo0 = goal_info(_, B, C, D, E, F, G, H, I, J, K),
-	GoalInfo = goal_info(PreBirths, B, C, D, E, F, G, H, I, J, K).
+	GoalInfo0 = goal_info(_, B, C, D, E, F, G, H, I, J, K, L),
+	GoalInfo = goal_info(PreBirths, B, C, D, E, F, G, H, I, J, K, L).
 
 goal_info_set_post_births(GoalInfo0, PostBirths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, _, C, D, E, F, G, H, I, J, K),
-	GoalInfo = goal_info(A, PostBirths, C, D, E, F, G, H, I, J, K).
+	GoalInfo0 = goal_info(A, _, C, D, E, F, G, H, I, J, K, L),
+	GoalInfo = goal_info(A, PostBirths, C, D, E, F, G, H, I, J, K, L).
 
 goal_info_set_pre_deaths(GoalInfo0, PreDeaths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, _, D, E, F, G, H, I, J, K),
-	GoalInfo = goal_info(A, B, PreDeaths, D, E, F, G, H, I, J, K).
+	GoalInfo0 = goal_info(A, B, _, D, E, F, G, H, I, J, K, L),
+	GoalInfo = goal_info(A, B, PreDeaths, D, E, F, G, H, I, J, K, L).
 
 goal_info_set_post_deaths(GoalInfo0, PostDeaths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, _, E, F, G, H, I, J, K),
-	GoalInfo = goal_info(A, B, C, PostDeaths, E, F, G, H, I, J, K).
+	GoalInfo0 = goal_info(A, B, C, _, E, F, G, H, I, J, K, L),
+	GoalInfo = goal_info(A, B, C, PostDeaths, E, F, G, H, I, J, K, L).
 
 goal_info_set_determinism(GoalInfo0, Determinism, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, _, F, G, H, I, J, K),
-	GoalInfo = goal_info(A, B, C, D, Determinism, F, G, H, I, J, K).
+	GoalInfo0 = goal_info(A, B, C, D, _, F, G, H, I, J, K, L),
+	GoalInfo = goal_info(A, B, C, D, Determinism, F, G, H, I, J, K, L).
 
 goal_info_set_instmap_delta(GoalInfo0, InstMapDelta, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, _, G, H, I, J, K),
-	GoalInfo = goal_info(A, B, C, D, E, InstMapDelta, G, H, I, J, K).
+	GoalInfo0 = goal_info(A, B, C, D, E, _, G, H, I, J, K, L),
+	GoalInfo = goal_info(A, B, C, D, E, InstMapDelta, G, H, I, J, K, L).
 
 goal_info_set_context(GoalInfo0, Context, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, _, H, I, J, K),
-	GoalInfo = goal_info(A, B, C, D, E, F, Context, H, I, J, K).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, _, H, I, J, K, L),
+	GoalInfo = goal_info(A, B, C, D, E, F, Context, H, I, J, K, L).
 
 goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, _, I, J, K),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, NonLocals, I, J, K).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, _, I, J, K, L),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, NonLocals, I, J, K, L).
 
 goal_info_set_follow_vars(GoalInfo0, FollowVars, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, _, J, K),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, FollowVars, J, K).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, _, J, K, L),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, FollowVars, J, K, L).
 
 goal_info_set_features(GoalInfo0, Features, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, _, K),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, Features, K).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, _, K, L),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, Features, K, L).
 
 goal_info_set_resume_point(GoalInfo0, ResumePoint, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, _),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, ResumePoint).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, _, L),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, ResumePoint, L).
+
+goal_info_set_goal_path(GoalInfo0, GoalPath, GoalInfo) :-
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, K, _),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, K, GoalPath).
 
 goal_info_get_code_model(GoalInfo, CodeModel) :-
 	goal_info_get_determinism(GoalInfo, Determinism),
@@ -789,7 +826,6 @@
 %-----------------------------------------------------------------------------%
 
 goal_info_resume_vars_and_loc(Resume, Vars, Locs) :-
-
 	(
 		Resume = resume_point(Vars, Locs)
 	;
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.173
diff -u -r1.173 hlds_out.m
--- hlds_out.m	1997/10/09 09:38:41	1.173
+++ hlds_out.m	1997/10/11 07:24:41
@@ -175,7 +175,7 @@
 :- implementation.
 
 :- import_module mercury_to_mercury, globals, options.
-:- import_module llds_out, prog_out, prog_util, (inst), instmap.
+:- import_module llds_out, prog_out, prog_util, (inst), instmap, trace.
 
 :- import_module bool, int, string, list, set, map, std_util, assoc_list.
 :- import_module term, term_io, varset, require, getopt.
@@ -655,6 +655,16 @@
 		;
 			[]
 		)
+	;
+		[]
+	),
+	( { string__contains_char(Verbose, 'P') } ->
+		{ goal_info_get_goal_path(GoalInfo, Path) },
+		{ trace__path_to_string(Path, PathStr) },
+		hlds_out__write_indent(Indent),
+		io__write_string("% goal path: "),
+		io__write_string(PathStr),
+		io__write_string("\n")
 	;
 		[]
 	),
Index: compiler/ite_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ite_gen.m,v
retrieving revision 1.49
diff -u -r1.49 ite_gen.m
--- ite_gen.m	1997/09/29 05:28:23	1.49
+++ ite_gen.m	1997/10/11 09:12:04
@@ -39,7 +39,7 @@
 
 :- implementation.
 
-:- import_module code_gen, code_util, options, globals.
+:- import_module code_gen, code_util, trace, options, globals.
 :- import_module bool, set, tree, list, map, std_util, require.
 
 ite_gen__generate_det_ite(CondGoal, ThenGoal, ElseGoal, StoreMap, Code) -->
@@ -115,6 +115,15 @@
 	code_info__maybe_discard_hp(MaybeHpSlot),
 
 		% Generate the then branch
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfoThen) } ->
+		{ ThenGoal = _ - ThenGoalInfo },
+		{ goal_info_get_goal_path(ThenGoalInfo, ThenPath) },
+		trace__generate_event_code(ite_then(ThenPath), TraceInfoThen,
+			ThenTraceCode)
+	;
+		{ ThenTraceCode = empty }
+	),
 	code_gen__generate_goal(CodeModel, ThenGoal, ThenCode),
 	code_info__generate_branch_end(CodeModel, StoreMap, ThenSaveCode),
 
@@ -126,6 +135,14 @@
 	code_info__maybe_restore_and_discard_hp(MaybeHpSlot, RestoreHPCode),
 
 		% Generate the else branch
+	( { MaybeTraceInfo = yes(TraceInfoElse) } ->
+		{ ElseGoal = _ - ElseGoalInfo },
+		{ goal_info_get_goal_path(ElseGoalInfo, ElsePath) },
+		trace__generate_event_code(ite_else(ElsePath), TraceInfoElse,
+			ElseTraceCode)
+	;
+		{ ElseTraceCode = empty }
+	),
 	code_gen__generate_goal(CodeModel, ElseGoal, ElseCode),
 	code_info__generate_branch_end(CodeModel, StoreMap, ElseSaveCode),
 
@@ -138,15 +155,17 @@
 		 tree(SaveTicketCode,
 		 tree(CondCode,
 		 tree(DiscardTicketCode,
+		 tree(ThenTraceCode,
 		 tree(ThenCode,
 		 tree(ThenSaveCode,
 		 tree(JumpToEndCode,
 		 tree(RestoreContCode,
 		 tree(RestoreHPCode,
 		 tree(RestoreTicketCode,
+		 tree(ElseTraceCode,
 		 tree(ElseCode,
 		 tree(ElseSaveCode,
-		      EndLabelCode)))))))))))))
+		      EndLabelCode)))))))))))))))
 	},
 	code_info__remake_with_store_map(StoreMap).
 
@@ -252,6 +271,15 @@
 	),
 
 		% Generate the then branch
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfoThen) } ->
+		{ ThenGoal = _ - ThenGoalInfo },
+		{ goal_info_get_goal_path(ThenGoalInfo, ThenPath) },
+		trace__generate_event_code(ite_then(ThenPath), TraceInfoThen,
+			ThenTraceCode)
+	;
+		{ ThenTraceCode = empty }
+	),
 	code_gen__generate_goal(model_non, ThenGoal, ThenCode),
 	code_info__generate_branch_end(model_non, StoreMap, ThenSaveCode),
 
@@ -263,6 +291,14 @@
 		RestoreTicketCode),
 
 		% Generate the else branch
+	( { MaybeTraceInfo = yes(TraceInfoElse) } ->
+		{ ElseGoal = _ - ElseGoalInfo },
+		{ goal_info_get_goal_path(ElseGoalInfo, ElsePath) },
+		trace__generate_event_code(ite_else(ElsePath), TraceInfoElse,
+			ElseTraceCode)
+	;
+		{ ElseTraceCode = empty }
+	),
 	code_gen__generate_goal(model_non, ElseGoal, ElseCode),
 	code_info__generate_branch_end(model_non, StoreMap, ElseSaveCode),
 
@@ -279,6 +315,7 @@
 		 tree(SoftCutCode,
 		 tree(FlushCode,
 		 tree(DiscardTicketCode,
+		 tree(ThenTraceCode,
 		 tree(ThenCode,
 		 tree(ThenSaveCode,
 		 tree(JumpToEndCode,
@@ -286,9 +323,10 @@
 		 tree(RestoreContCode,
 		 tree(RestoreHPCode,
 		 tree(RestoreTicketCode,
+		 tree(ElseTraceCode,
 		 tree(ElseCode,
 		 tree(ElseSaveCode,
-		      EndLabelCode))))))))))))))))))
+		      EndLabelCode))))))))))))))))))))
 	},
 	code_info__remake_with_store_map(StoreMap).
 
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.57
diff -u -r1.57 mercury_compile.m
--- mercury_compile.m	1997/10/09 09:38:51	1.57
+++ mercury_compile.m	1997/10/11 07:24:50
@@ -36,7 +36,7 @@
 :- import_module (lambda), polymorphism, termination, higher_order, inlining.
 :- import_module dnf, constraint, unused_args, dead_proc_elim, saved_vars.
 :- import_module lco, liveness, stratify.
-:- import_module follow_code, live_vars, arg_info, store_alloc.
+:- import_module follow_code, live_vars, arg_info, store_alloc, goal_path.
 :- import_module code_gen, optimize, export, base_type_info, base_type_layout.
 :- import_module llds_common, llds_out.
 
@@ -742,9 +742,12 @@
 	mercury_compile__allocate_store_map(HLDS65, Verbose, Stats, HLDS68), !,
 	mercury_compile__maybe_dump_hlds(HLDS68, "68", "store_map"), !,
 
-	maybe_report_sizes(HLDS68),
+	mercury_compile__maybe_goal_paths(HLDS68, Verbose, Stats, HLDS72), !,
+	mercury_compile__maybe_dump_hlds(HLDS72, "72", "goal_path"), !,
 
-	{ HLDS90 = HLDS68 },
+	maybe_report_sizes(HLDS72),
+
+	{ HLDS90 = HLDS72 },
 	mercury_compile__maybe_dump_hlds(HLDS90, "90", "precodegen"), !,
 
 	mercury_compile__generate_code(HLDS90, Verbose, Stats, HLDS95, LLDS1),
@@ -864,12 +867,21 @@
 		"% Allocating storage locations for live vars in ",
 				PredId, ProcId, ModuleInfo3),
 	{ store_alloc_in_proc(ProcInfo5, ModuleInfo3, ProcInfo6) },
-	{ module_info_get_continuation_info(ModuleInfo3, ContInfo0) },
-	{ module_info_get_cell_count(ModuleInfo3, CellCount0) },
+	{ globals__lookup_bool_option(Globals, generate_trace, Trace) },
+	( { Trace = yes } ->
+		write_proc_progress_message(
+			"% Calculating goal paths in ",
+					PredId, ProcId, ModuleInfo3),
+		{ goal_path__fill_slots(ProcInfo6, ModuleInfo3, ProcInfo7) }
+	;
+		{ ProcInfo7 = ProcInfo6 }
+	),
 	write_proc_progress_message(
 		"% Generating low-level (LLDS) code for ",
 				PredId, ProcId, ModuleInfo3),
-	{ generate_proc_code(ProcInfo6, ProcId, PredId, ModuleInfo3, Globals,
+	{ module_info_get_continuation_info(ModuleInfo3, ContInfo0) },
+	{ module_info_get_cell_count(ModuleInfo3, CellCount0) },
+	{ generate_proc_code(ProcInfo7, ProcId, PredId, ModuleInfo3, Globals,
 		ContInfo0, CellCount0, ContInfo, CellCount, Proc0) },
 	{ module_info_set_continuation_info(ModuleInfo3, ContInfo, 
 		ModuleInfo4) },
@@ -1428,6 +1440,24 @@
 		HLDS0, HLDS),
 	maybe_write_string(Verbose, " done.\n"),
 	maybe_report_stats(Stats).
+
+:- pred mercury_compile__maybe_goal_paths(module_info, bool, bool,
+	module_info, io__state, io__state).
+:- mode mercury_compile__maybe_goal_paths(in, in, in, out, di, uo) is det.
+
+mercury_compile__maybe_goal_paths(HLDS0, Verbose, Stats, HLDS) -->
+	globals__io_lookup_bool_option(generate_trace, Trace),
+	( { Trace = yes } ->
+		maybe_write_string(Verbose, "% Calculating goal paths..."),
+		maybe_flush_output(Verbose),
+		process_all_nonimported_procs(
+			update_proc(goal_path__fill_slots),
+			HLDS0, HLDS),
+		maybe_write_string(Verbose, " done.\n"),
+		maybe_report_stats(Stats)
+	;
+		{ HLDS = HLDS0 }
+	).
 
 :- pred mercury_compile__generate_code(module_info, bool, bool, module_info,
 	list(c_procedure), io__state, io__state).
Index: compiler/string_switch.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/string_switch.m,v
retrieving revision 1.23
diff -u -r1.23 string_switch.m
--- string_switch.m	1997/07/27 15:01:42	1.23
+++ string_switch.m	1997/10/11 08:14:57
@@ -29,7 +29,7 @@
 
 :- implementation.
 
-:- import_module hlds_data, code_gen, tree.
+:- import_module hlds_data, code_gen, trace, tree.
 :- import_module bool, int, string, list, map, std_util, assoc_list, require.
 
 string_switch__generate(Cases, Var, CodeModel, _CanFail, StoreMap,
@@ -301,6 +301,15 @@
 		{ LabelCode = node([
 			label(Label) - Comment
 		]) },
+		code_info__get_maybe_trace_info(MaybeTraceInfo),
+		( { MaybeTraceInfo = yes(TraceInfo) } ->
+			{ Goal = _ - GoalInfo },
+			{ goal_info_get_goal_path(GoalInfo, Path) },
+			trace__generate_event_code(switch(Path), TraceInfo,
+				TraceCode)
+		;
+			{ TraceCode = empty }
+		),
 		(
 			{ string_switch__this_is_last_case(Slot, TblSize,
 				HashSlotMap) }
@@ -320,9 +329,10 @@
 		]) },
 		{ Code =
 			tree(LabelCode,
+			tree(TraceCode,
 			tree(GoalCode,
 			tree(SaveCode,
-			     FinishCode)))
+			     FinishCode))))
 		}
 	;
 		{ StringRval = const(int_const(0)) },
Index: compiler/switch_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/switch_gen.m,v
retrieving revision 1.59
diff -u -r1.59 switch_gen.m
--- switch_gen.m	1997/07/27 15:01:44	1.59
+++ switch_gen.m	1997/10/11 08:19:32
@@ -62,7 +62,7 @@
 
 :- import_module dense_switch, string_switch, tag_switch, lookup_switch.
 :- import_module llds, code_gen, unify_gen, code_aux, type_util, code_util.
-:- import_module globals, options.
+:- import_module trace, globals, options.
 :- import_module bool, int, string, list, map, tree, std_util, require.
 
 :- type switch_category
@@ -88,6 +88,8 @@
 	(
 		{ Indexing = yes },
 		{ SwitchCategory = atomic_switch },
+		code_info__get_maybe_trace_info(MaybeTraceInfo),
+		{ MaybeTraceInfo = no },
 		{ list__length(TaggedCases, NumCases) },
 		{ globals__lookup_int_option(Globals, lookup_switch_size,
 			LookupSize) },
@@ -301,6 +303,15 @@
 
 switch_gen__generate_cases([case(_, _, Cons, Goal) | Cases], Var, CodeModel,
 		CanFail, StoreMap, EndLabel, CasesCode) -->
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ Goal = _ - GoalInfo },
+		{ goal_info_get_goal_path(GoalInfo, Path) },
+		trace__generate_event_code(switch(Path), TraceInfo,
+			TraceCode)
+	;
+		{ TraceCode = empty }
+	),
 	code_info__grab_code_info(CodeInfo0),
 	(
 		{ Cases = [_|_] ; CanFail = can_fail }
@@ -317,16 +328,21 @@
 		]) },
 		{ ThisCaseCode =
 			tree(TestCode,
+			tree(TraceCode,
 			tree(GoalCode,
 			tree(SaveCode,
-			     ElseCode)))
+			     ElseCode))))
 		},
 		code_info__grab_code_info(CodeInfo1),
 		code_info__slap_code_info(CodeInfo0)
 	;
 		code_gen__generate_goal(CodeModel, Goal, GoalCode),
 		code_info__generate_branch_end(CodeModel, StoreMap, SaveCode),
-		{ ThisCaseCode = tree(GoalCode, SaveCode) },
+		{ ThisCaseCode =
+			tree(TraceCode,
+			tree(GoalCode,
+			     SaveCode))
+		},
 		code_info__grab_code_info(CodeInfo1),
 		code_info__slap_code_info(CodeInfo0)
 	),
Index: compiler/tag_switch.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/tag_switch.m,v
retrieving revision 1.39
diff -u -r1.39 tag_switch.m
--- tag_switch.m	1997/08/22 13:56:04	1.39
+++ tag_switch.m	1997/10/11 08:15:11
@@ -25,7 +25,7 @@
 
 :- implementation.
 
-:- import_module hlds_module, hlds_pred, hlds_data, code_gen.
+:- import_module hlds_module, hlds_pred, hlds_data, code_gen, trace.
 :- import_module options, globals, type_util, prog_data.
 :- import_module assoc_list, bool, map, tree, int, require, std_util, term.
 
@@ -493,6 +493,15 @@
 	->
 		% There is no secondary tag, so there is no switch on it
 		( { GoalList = [-1 - Goal] } ->
+			code_info__get_maybe_trace_info(MaybeTraceInfo),
+			( { MaybeTraceInfo = yes(TraceInfo) } ->
+				{ Goal = _ - GoalInfo },
+				{ goal_info_get_goal_path(GoalInfo, Path) },
+				trace__generate_event_code(switch(Path),
+					TraceInfo, TraceCode)
+			;
+				{ TraceCode = empty }
+			),
 			code_gen__generate_goal(CodeModel, Goal, GoalCode),
 			code_info__generate_branch_end(CodeModel, StoreMap,
 				SaveCode),
@@ -501,9 +510,10 @@
 					"skip to end of primary tag switch"
 			]) },
 			{ Code =
+				tree(TraceCode,
 				tree(GoalCode,
 				tree(SaveCode,
-				     GotoCode))
+				     GotoCode)))
 			}
 		; { GoalList = [] } ->
 			{ error("no goal for non-shared tag") }
@@ -612,6 +622,15 @@
 tag_switch__generate_secondary_try_me_else_chain([Case0 | Cases0], StagRval,
 		CodeModel, CanFail, StoreMap, EndLabel, FailLabel, Code) -->
 	{ Case0 = Secondary - Goal },
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ Goal = _ - GoalInfo },
+		{ goal_info_get_goal_path(GoalInfo, Path) },
+		trace__generate_event_code(switch(Path), TraceInfo,
+			TraceCode)
+	;
+		{ TraceCode = empty }
+	),
 	( { Cases0 = [_|_] ; CanFail = can_fail } ->
 		code_info__grab_code_info(CodeInfo),
 		code_info__get_next_label(ElseLabel),
@@ -631,9 +650,10 @@
 		]) },
 		{ ThisCode =
 			tree(TestCode,
+			tree(TraceCode,
 			tree(GoalCode,
 			tree(SaveCode,
-			     GotoLabelCode)))
+			     GotoLabelCode))))
 		},
 		( { Cases0 = [_|_] } ->
 			code_info__slap_code_info(CodeInfo),
@@ -656,9 +676,10 @@
 				"skip to end of secondary tag switch"
 		]) },
 		{ Code =
+			tree(TraceCode,
 			tree(GoalCode,
 			tree(SaveCode,
-			     GotoCode))
+			     GotoCode)))
 		}
 	).
 
@@ -678,6 +699,15 @@
 		CodeModel, CanFail, StoreMap, EndLabel, FailLabel,
 		PrevTests0, PrevCases0, Code) -->
 	{ Case0 = Secondary - Goal },
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ Goal = _ - GoalInfo },
+		{ goal_info_get_goal_path(GoalInfo, Path) },
+		trace__generate_event_code(switch(Path), TraceInfo,
+			TraceCode)
+	;
+		{ TraceCode = empty }
+	),
 	( { Cases0 = [_|_] ; CanFail = can_fail } ->
 		code_info__grab_code_info(CodeInfo),
 		code_info__get_next_label(ThisStagLabel),
@@ -699,9 +729,10 @@
 		]) },
 		{ ThisCode =
 			tree(LabelCode,
+			tree(TraceCode,
 			tree(GoalCode,
 			tree(SaveCode,
-			     GotoCode)))
+			     GotoCode))))
 		},
 		{ PrevTests = tree(PrevTests0, TestCode) },
 		{ PrevCases = tree(ThisCode, PrevCases0) },
@@ -727,10 +758,11 @@
 		]) },
 		{ Code =
 			tree(PrevTests0,
+			tree(TraceCode,
 			tree(GoalCode,
 			tree(SaveCode,
 			tree(GotoCode,
-			     PrevCases0))))
+			     PrevCases0)))))
 		}
 	).
 
@@ -763,6 +795,15 @@
 				label(NewLabel) -
 					"start of case in secondary tag switch"
 			]) },
+			code_info__get_maybe_trace_info(MaybeTraceInfo),
+			( { MaybeTraceInfo = yes(TraceInfo) } ->
+				{ Goal = _ - GoalInfo },
+				{ goal_info_get_goal_path(GoalInfo, Path) },
+				trace__generate_event_code(switch(Path),
+					TraceInfo, TraceCode)
+			;
+				{ TraceCode = empty }
+			),
 			( { CaseList1 = [] } ->
 				code_gen__generate_goal(CodeModel, Goal,
 					GoalCode),
@@ -787,10 +828,11 @@
 			{ Labels = [NewLabel | OtherLabels] },
 			{ Code =
 				tree(LabelCode,
+				tree(TraceCode,
 				tree(GoalCode,
 				tree(SaveCode,
 				tree(GotoCode,
-				     OtherCode))))
+				     OtherCode)))))
 			}
 		;
 			tag_switch__generate_secondary_jump_table(CaseList,
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.1
diff -u -r1.1 trace.m
--- trace.m	1997/10/03 04:55:48	1.1
+++ trace.m	1997/10/11 08:52:35
@@ -25,11 +25,15 @@
 
 :- interface.
 
-:- import_module llds, code_info.
+:- import_module hlds_goal, llds, code_info.
 
 :- type trace_port	--->	call
 			;	exit
-			;	fail.
+			;	fail
+			;	ite_then(goal_path)
+			;	ite_else(goal_path)
+			;	switch(goal_path)
+			;	disj(goal_path).
 
 :- type trace_info.
 
@@ -42,6 +46,8 @@
 :- pred trace__generate_event_code(trace_port::in, trace_info::in,
 	code_tree::out, code_info::in, code_info::out) is det.
 
+:- pred trace__path_to_string(goal_path::in, string::out) is det.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -102,35 +108,62 @@
 	proc_id_to_int(ProcId, ProcInt),
 	ModeNum is ProcInt mod 10000,
 	string__int_to_string(ModeNum, ModeNumStr),
-	string__append_list([
-		"MR_trace(",
-		PortStr, ", ",
-		CodeModelStr, ", ",
-		CallNumStr, ", ",
-		CallDepthStr, ", ",
-		Quote, ModuleName, Quote, ", ",
-		Quote, PredName, Quote, ", ",
-		ArityStr, ", ",
-		ModeNumStr, ");\n"],
-		TraceStmt),
+	( trace__port_path(Port, Path) ->
+		trace__path_to_string(Path, PathStr),
+		string__append_list([
+			"MR_trace_path(",
+			PortStr, ", ",
+			CodeModelStr, ", ",
+			CallNumStr, ", ",
+			CallDepthStr, ", ",
+			Quote, ModuleName, Quote, ", ",
+			Quote, PredName, Quote, ", ",
+			ArityStr, ", ",
+			ModeNumStr, ", ",
+			Quote, PathStr, Quote, ");\n"],
+			TraceStmt)
+	;
+		string__append_list([
+			"MR_trace(",
+			PortStr, ", ",
+			CodeModelStr, ", ",
+			CallNumStr, ", ",
+			CallDepthStr, ", ",
+			Quote, ModuleName, Quote, ", ",
+			Quote, PredName, Quote, ", ",
+			ArityStr, ", ",
+			ModeNumStr, ");\n"],
+			TraceStmt)
+	),
 	TraceCode = node([c_code(TraceStmt) - ""])
 	}.
 
+%-----------------------------------------------------------------------------%
+
+:- pred trace__port_path(trace_port::in, goal_path::out) is semidet.
+
+trace__port_path(ite_then(Path), Path).
+trace__port_path(ite_else(Path), Path).
+trace__port_path(switch(Path),   Path).
+trace__port_path(disj(Path),     Path).
+
 :- pred trace__port_to_string(trace_port::in, string::out) is det.
 
 trace__port_to_string(call, "MR_PORT_CALL").
 trace__port_to_string(exit, "MR_PORT_EXIT").
 trace__port_to_string(fail, "MR_PORT_FAIL").
+trace__port_to_string(ite_then(_), "MR_PORT_THEN").
+trace__port_to_string(ite_else(_), "MR_PORT_ELSE").
+trace__port_to_string(switch(_),   "MR_PORT_SWITCH").
+trace__port_to_string(disj(_),     "MR_PORT_DISJ").
 
-:- pred trace__code_model_to_string(code_model, string).
-:- mode trace__code_model_to_string(in, out) is det.
+:- pred trace__code_model_to_string(code_model::in, string::out) is det.
 
 trace__code_model_to_string(model_det,  "MR_MODEL_DET").
 trace__code_model_to_string(model_semi, "MR_MODEL_SEMI").
 trace__code_model_to_string(model_non,  "MR_MODEL_NON").
 
-:- pred trace__stackref_to_string(lval, string).
-:- mode trace__stackref_to_string(in, out) is det.
+:- pred trace__stackref_to_string(lval::in, string::out) is det.
 
 trace__stackref_to_string(Lval, LvalStr) :-
 	( Lval = stackvar(Slot) ->
@@ -142,3 +175,34 @@
 	;
 		error("non-stack lval in stackref_to_string")
 	).
+
+%-----------------------------------------------------------------------------%
+
+trace__path_to_string(Path, PathStr) :-
+	trace__path_steps_to_strings(Path, StepStrs),
+	list__reverse(StepStrs, RevStepStrs),
+	string__append_list(RevStepStrs, PathStr).
+
+:- pred trace__path_steps_to_strings(goal_path::in, list(string)::out) is det.
+
+trace__path_steps_to_strings([], []).
+trace__path_steps_to_strings([Step | Steps], [StepStr | StepStrs]) :-
+	trace__path_step_to_string(Step, StepStr),
+	trace__path_steps_to_strings(Steps, StepStrs).
+
+:- pred trace__path_step_to_string(goal_path_step::in, string::out) is det.
+
+trace__path_step_to_string(conj(N), Str) :-
+	string__int_to_string(N, NStr),
+	string__append_list(["c", NStr, ";"], Str).
+trace__path_step_to_string(disj(N), Str) :-
+	string__int_to_string(N, NStr),
+	string__append_list(["d", NStr, ";"], Str).
+trace__path_step_to_string(switch(N), Str) :-
+	string__int_to_string(N, NStr),
+	string__append_list(["s", NStr, ";"], Str).
+trace__path_step_to_string(ite_cond, "?;").
+trace__path_step_to_string(ite_then, "t;").
+trace__path_step_to_string(ite_else, "e;").
+trace__path_step_to_string(neg, "~;").
+trace__path_step_to_string(exist, "q;").
Index: runtime/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.c,v
retrieving revision 1.1
diff -u -r1.1 mercury_trace.c
--- mercury_trace.c	1997/10/03 04:56:31	1.1
+++ mercury_trace.c	1997/10/11 07:07:38
@@ -45,6 +45,9 @@
 		case MR_PORT_FAIL:
 			fprintf(stderr, "FAIL ");
 			break;
+
+		default:
+			fatal_error("MR_trace called with inappropriate port");
 	}
 
 	switch (model)
@@ -63,4 +66,60 @@
 	}
 
 	fprintf(stderr, "%s:%s/%d-%d\n", modulename, predname, arity, modenum);
+}
+
+void
+MR_trace_path(MR_trace_port port, MR_trace_code_model model,
+	int seqno, int depth,
+	const char *modulename, const char *predname, int arity, int modenum,
+	const char *path)
+{
+	int	i;
+
+	fprintf(stderr, "%4d %2d ", seqno, depth);
+
+	for (i = 0; i < depth; i++)
+	{
+		putc(' ', stderr);
+	}
+
+	switch (port)
+	{
+		case MR_PORT_THEN:
+			fprintf(stderr, "THEN ");
+			break;
+
+		case MR_PORT_ELSE:
+			fprintf(stderr, "ELSE ");
+			break;
+
+		case MR_PORT_DISJ:
+			fprintf(stderr, "DISJ ");
+			break;
+
+		case MR_PORT_SWITCH:
+			fprintf(stderr, "SWTC ");
+			break;
+
+		default:
+			fatal_error("MR_trace_path called with inappropriate port");
+	}
+
+	switch (model)
+	{
+		case MR_MODEL_DET:
+			fprintf(stderr, "DET  ");
+			break;
+
+		case MR_MODEL_SEMI:
+			fprintf(stderr, "SEMI ");
+			break;
+
+		case MR_MODEL_NON:
+			fprintf(stderr, "NON  ");
+			break;
+	}
+
+	fprintf(stderr, "%s:%s/%d-%d %s\n",
+		modulename, predname, arity, modenum, path);
 }
Index: runtime/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_trace.h
--- mercury_trace.h	1997/10/07 06:22:05	1.2
+++ mercury_trace.h	1997/10/11 07:28:16
@@ -24,7 +24,8 @@
 extern	int	MR_trace_call_depth;
 
 typedef	enum {
-	MR_PORT_CALL, MR_PORT_EXIT, MR_PORT_FAIL
+	MR_PORT_CALL, MR_PORT_EXIT, MR_PORT_FAIL,
+	MR_PORT_THEN, MR_PORT_ELSE, MR_PORT_DISJ, MR_PORT_SWITCH
 } MR_trace_port;
 
 typedef	enum {
@@ -40,5 +41,16 @@
 	const char *,		/* predicate name */
 	int,			/* predicate arity */
 	int);			/* mode number within predicate */
+
+extern	void	MR_trace_path(
+	MR_trace_port,
+	MR_trace_code_model,
+	int,			/* call sequence number */
+	int,			/* call depth */
+	const char *,		/* module name */
+	const char *,		/* predicate name */
+	int,			/* predicate arity */
+	int,			/* mode number within predicate */
+	const char *);		/* path to event goal within procedure */
 
 #endif /* MERCURY_TRACE_H */

New File: compiler/goal_path.m
===================================================================
%-----------------------------------------------------------------------------%
% Copyright (C) 1997 University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%

% This module looks after goal paths, which associate each goal
% with its position in a procedure definition,

% Main author: zs.

:- module goal_path.

:- interface.

:- import_module hlds_pred, hlds_module.

:- pred goal_path__fill_slots(proc_info::in, module_info::in, proc_info::out)
	is det.

:- implementation.

:- import_module hlds_goal.
:- import_module int, list, std_util.

goal_path__fill_slots(Proc0, _ModuleInfo, Proc) :-
		% The ModuleInfo argument is there just for passes_aux
	proc_info_goal(Proc0, Goal0),
	fill_goal_slots(Goal0, [], Goal),
	proc_info_set_goal(Proc0, Goal, Proc).

:- pred fill_goal_slots(hlds_goal::in, goal_path::in, hlds_goal::out) is det.

fill_goal_slots(Expr0 - Info0, Path0, Expr - Info) :-
	goal_info_set_goal_path(Info0, Path0, Info),
	fill_expr_slots(Expr0, Path0, Expr).

:- pred fill_expr_slots(hlds_goal_expr::in, goal_path::in,
	hlds_goal_expr::out) is det.

fill_expr_slots(conj(Goals0), Path0, conj(Goals)) :-
	fill_conj_slots(Goals0, Path0, 0, Goals).
fill_expr_slots(disj(Goals0, B), Path0, disj(Goals, B)) :-
	fill_disj_slots(Goals0, Path0, 0, Goals).
fill_expr_slots(switch(A, B, Cases0, D), Path0, switch(A, B, Cases, D)) :-
	fill_switch_slots(Cases0, Path0, 0, Cases).
fill_expr_slots(not(Goal0), Path0, not(Goal)) :-
	fill_goal_slots(Goal0, [neg | Path0], Goal).
fill_expr_slots(some(A, Goal0), Path0, some(A, Goal)) :-
	fill_goal_slots(Goal0, [exist | Path0], Goal).
fill_expr_slots(if_then_else(A, Cond0, Then0, Else0, E), Path0,
		if_then_else(A, Cond, Then, Else, E)) :-
	fill_goal_slots(Cond0, [ite_cond | Path0], Cond),
	fill_goal_slots(Then0, [ite_then | Path0], Then),
	fill_goal_slots(Else0, [ite_else | Path0], Else).
fill_expr_slots(call(A,B,C,D,E,F), _Path0, call(A,B,C,D,E,F)).
fill_expr_slots(higher_order_call(A,B,C,D,E,F), _Path0,
		higher_order_call(A,B,C,D,E,F)).
fill_expr_slots(unify(A,B,C,D,E), _Path0, unify(A,B,C,D,E)).
fill_expr_slots(pragma_c_code(A,B,C,D,E,F,G,H), _Path0,
		pragma_c_code(A,B,C,D,E,F,G,H)).

:- pred fill_conj_slots(list(hlds_goal)::in, goal_path::in, int::in,
	list(hlds_goal)::out) is det.

fill_conj_slots([], _, _, []).
fill_conj_slots([Goal0 | Goals0], Path0, N0, [Goal | Goals]) :-
	N1 is N0 + 1,
	fill_goal_slots(Goal0, [conj(N1) | Path0], Goal),
	fill_conj_slots(Goals0, Path0, N1, Goals).

:- pred fill_disj_slots(list(hlds_goal)::in, goal_path::in, int::in,
	list(hlds_goal)::out) is det.

fill_disj_slots([], _, _, []).
fill_disj_slots([Goal0 | Goals0], Path0, N0, [Goal | Goals]) :-
	N1 is N0 + 1,
	fill_goal_slots(Goal0, [disj(N1) | Path0], Goal),
	fill_disj_slots(Goals0, Path0, N1, Goals).

:- pred fill_switch_slots(list(case)::in, goal_path::in, int::in,
	list(case)::out) is det.

fill_switch_slots([], _, _, []).
fill_switch_slots([case(A, Goal0) | Cases0], Path0, N0,
		[case(A, Goal) | Cases]) :-
	N1 is N0 + 1,
	fill_goal_slots(Goal0, [switch(N1) | Path0], Goal),
	fill_switch_slots(Cases0, Path0, N1, Cases).




More information about the developers mailing list