[m-dev.] for review: line numbers in the debugger (part 1)

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Nov 10 15:47:30 AEDT 1999


Estimated hours taken: 

Support breakpoints on line numbers that correspond to calls. Internally,
these are implemented as breakpoints on the proc layouts of the called
procedure.

This required extending the debugging RTTI, so that associated with each
module there is now a new data structure listing the source file names that
contribute labels with layout structures to the code of the module. For each
such source file, this table gives a list of all such labels arising from
that file. The table entry for a label gives the line number within the file,
and the pointer to the label layout structure.

compiler/llds.m:
	Add a context field to the call instruction.

compiler/continuation_info.m:
	Instead of the old division of continuation info about labels into
	trace ports and everything else, divide them into trace ports, resume
	points and return sites. Record contexts with trace ports, and record
	contexts and called procedure information with return sites.

compiler/code_info.m:
	Conform to the changes in continuation_info.m.

compiler/options.m:
	Add a new option that allows us to disable the generation of line
	number information for size benchmarking (it has no other use).

compiler/stack_layout.m:
	Generate the new components of the RTTI, unless the option says not to.

compiler/code_gen.m:
compiler/pragma_c_gen.m:
compiler/trace.m:
	Include contexts in the events we generate.

compiler/call_gen.m:
	Include contexts in the call LLDS instructions.

compiler/handle_options.m:
	Delete the code that tests or sets the deleted options.

compiler/mercury_compile.m:
	Delete the code that tests the deleted options.

compiler/basic_block.m:
compiler/dupelim.m:
compiler/frameopt.m:
compiler/livemap.m:
compiler/llds_common.m:
compiler/llds_out.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/value_number.m:
compiler/vn_*.m:
	Trivial changes to conform to the changes to llds.m.

compiler/jumpopt.m:
	Do not optimize away jumps to labels with layout structures.
	The jumps we are particularly concerned about now are the jumps
	that return from procedure calls. Previously, it was okay to redirect
	returns from several calls so that all go to the same label, since
	the live variable information associated with the labels could be
	merged. However, we now also associate line numbers with calls, and
	these cannot be usefully merged.

compiler/optimize.m:
	Pass the information required by jumpopt to it.

doc/user_guide.texi:
	Document that you can now break at line numbers.

	Document the new "context" command, and the -d or --detailed option
	of the stack command and the commands that set ancestor levels.

runtime/mercury_stack_layout.h:
	Extend the module layout structure definition with the new tables.

	Remove the conditional facility for including label numbers in label
	layout structures. It hasn't been used in a long time, and neither
	Tyson or me expect to use it to debug either gc or the debugger itself,
	so it has no uses left; the line numbers have superseded it.

runtime/mercury_stack_trace.[ch]:
	Extend the code to print stack traces to also optionally print
	contexts.

	Add some utility predicates currently used by the debugger that could
	also be use for debugging gc or for more detailed stack traces.

trace/mercury_trace_internal.c:
	Implement the "break <context>" command, the "context" command, and
	the -d or --detailed option of the stack command and the commands
	that set ancestor levels.

	Conditionally define a conditionally used variable.

trace/mercury_trace_external.c:
	Minor changes to keep up with the changes to stack traces.

	Delete an unused variable.

trace/mercury_trace_spy.[ch]:
	Check for breakpoints on contexts.

trace/mercury_trace_tables.[ch]:
	Add functions to search the RTTI data structures for labels
	corresponding to a given context.

trace/mercury_trace_vars.[ch]:
	Remember the context of the current environment.

tests/debugger/queen.{inp,exp}:
	Test the new capabilities of the debugger.

tests/debugger/*.{inp,exp}:
	Update the expected output of the debugger to account for contexts.
	In some cases, modify the input script to put contexts where they don't
	overflow lines.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/basic_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/basic_block.m,v
retrieving revision 1.7
diff -u -b -r1.7 basic_block.m
--- basic_block.m	1998/07/29 08:52:45	1.7
+++ basic_block.m	1999/10/10 06:37:56
@@ -154,7 +154,7 @@
 possible_targets(block(_, _, _), _) :-
 	error("block in possible_targets").
 possible_targets(assign(_, _), []).
-possible_targets(call(_, ReturnAddr, _, _), Labels) :-
+possible_targets(call(_, ReturnAddr, _, _, _), Labels) :-
 	( ReturnAddr = label(Label) ->
 		Labels = [Label]
 	;
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.136
diff -u -b -r1.136 call_gen.m
--- call_gen.m	1999/10/15 13:51:04	1.136
+++ call_gen.m	1999/10/19 04:15:33
@@ -112,8 +112,10 @@
 	code_info__make_entry_label(ModuleInfo, PredId, ModeId, yes, Address),
 	code_info__get_next_label(ReturnLabel),
 	{ call_gen__call_comment(CodeModel, CallComment) },
+	{ goal_info_get_context(GoalInfo, Context) },
 	{ CallCode = node([
-		call(Address, label(ReturnLabel), ReturnLiveLvalues, CallModel)
+		call(Address, label(ReturnLabel), ReturnLiveLvalues, Context,
+			CallModel)
 			- CallComment,
 		label(ReturnLabel)
 			- "continuation label"
@@ -194,11 +196,12 @@
 		ReturnLiveLvalues),
 
 	code_info__get_next_label(ReturnLabel),
+	{ goal_info_get_context(GoalInfo, Context) },
 	{ CallCode = node([
 		livevals(LiveVals)
 			- "",
 		call(CodeAddr, label(ReturnLabel), ReturnLiveLvalues,
-			CallModel)
+			Context, CallModel)
 			- "Setup and call",
 		label(ReturnLabel)
 			- "Continuation label"
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.68
diff -u -b -r1.68 code_gen.m
--- code_gen.m	1999/10/25 03:48:38	1.68
+++ code_gen.m	1999/10/25 07:34:25
@@ -200,6 +200,7 @@
 	;
 		SaveSuccip = no
 	),
+
 		% Initialise the code_info structure. Generate_category_code
 		% below will use the returned OutsideResumePoint as the
 		% entry to the code that handles the failure of the procedure,
@@ -235,6 +236,7 @@
 	;
 		Instructions = Instructions0
 	),
+
 	( BasicStackLayout = yes ->
 			% Create the procedure layout structure.
 		code_info__get_layout_info(InternalMap, CodeInfo, _),
@@ -248,6 +250,7 @@
 	;
 		GlobalData1 = GlobalData0
 	),
+
 	code_info__get_non_common_static_data(NonCommonStatics, CodeInfo, _),
 	global_data_add_new_non_common_static_datas(GlobalData1,
 		NonCommonStatics, GlobalData2),
@@ -342,10 +345,13 @@
 		{ MaybeTraceCallLabel = no },
 		{ FrameInfo = frame(0, no, no) }
 	;
+		{ Goal = _ - GoalInfo },
+		{ goal_info_get_context(GoalInfo, BodyContext) },
 		code_info__get_maybe_trace_info(MaybeTraceInfo),
 		( { MaybeTraceInfo = yes(TraceInfo) } ->
 			trace__generate_external_event_code(call, TraceInfo,
-				TraceCallLabel, _TypeInfos, TraceCallCode),
+				BodyContext, TraceCallLabel, _TypeInfos,
+				TraceCallCode),
 			{ MaybeTraceCallLabel = yes(TraceCallLabel) }
 		;
 			{ TraceCallCode = empty },
@@ -355,7 +361,7 @@
 		code_gen__generate_entry(model_det, Goal, ResumePoint,
 			FrameInfo, EntryCode),
 		code_gen__generate_exit(model_det, FrameInfo, TraceSlotInfo,
-			_, ExitCode),
+			BodyContext, _, ExitCode),
 		{ Code =
 			tree(EntryCode,
 			tree(TraceCallCode,
@@ -372,23 +378,28 @@
 		livevals(FailureLiveRegs) - "",
 		goto(succip) - "Return from procedure call"
 	]) },
+	{ Goal = _ - GoalInfo },
+	{ goal_info_get_context(GoalInfo, BodyContext) },
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
 	( { MaybeTraceInfo = yes(TraceInfo) } ->
 		trace__generate_external_event_code(call, TraceInfo,
-			TraceCallLabel, _TypeInfos, TraceCallCode),
+			BodyContext, TraceCallLabel, _TypeInfos,
+			TraceCallCode),
 		{ MaybeTraceCallLabel = yes(TraceCallLabel) },
 		code_gen__generate_goal(model_semi, Goal, BodyCode),
 		code_gen__generate_entry(model_semi, Goal, ResumePoint,
 			FrameInfo, EntryCode),
 		code_gen__generate_exit(model_semi, FrameInfo, TraceSlotInfo,
-			RestoreDeallocCode, ExitCode),
+			BodyContext, RestoreDeallocCode, ExitCode),
 
 		code_info__generate_resume_point(ResumePoint, ResumeCode),
 		{ code_info__resume_point_vars(ResumePoint, ResumeVarList) },
 		{ set__list_to_set(ResumeVarList, ResumeVars) },
 		code_info__set_forward_live_vars(ResumeVars),
-		trace__generate_external_event_code(fail, TraceInfo, _, _,
-			TraceFailCode),
+			% XXX A context that gives the end of the procedure
+			% definition would be better than BodyContext.
+		trace__generate_external_event_code(fail, TraceInfo,
+			BodyContext, _, _, TraceFailCode),
 		{ Code =
 			tree(EntryCode,
 			tree(TraceCallCode,
@@ -405,7 +416,7 @@
 		code_gen__generate_entry(model_semi, Goal, ResumePoint,
 			FrameInfo, EntryCode),
 		code_gen__generate_exit(model_semi, FrameInfo, TraceSlotInfo,
-			RestoreDeallocCode, ExitCode),
+			BodyContext, RestoreDeallocCode, ExitCode),
 		code_info__generate_resume_point(ResumePoint, ResumeCode),
 		{ Code =
 			tree(EntryCode,
@@ -420,22 +431,27 @@
 generate_category_code(model_non, Goal, ResumePoint, TraceSlotInfo, Code,
 		MaybeTraceCallLabel, FrameInfo) -->
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	{ Goal = _ - GoalInfo },
+	{ goal_info_get_context(GoalInfo, BodyContext) },
 	( { MaybeTraceInfo = yes(TraceInfo) } ->
 		trace__generate_external_event_code(call, TraceInfo,
-			TraceCallLabel, _TypeInfos, TraceCallCode),
+			BodyContext, TraceCallLabel, _TypeInfos,
+			TraceCallCode),
 		{ MaybeTraceCallLabel = yes(TraceCallLabel) },
 		code_gen__generate_goal(model_non, Goal, BodyCode),
 		code_gen__generate_entry(model_non, Goal, ResumePoint,
 			FrameInfo, EntryCode),
 		code_gen__generate_exit(model_non, FrameInfo, TraceSlotInfo,
-			_, ExitCode),
+			BodyContext, _, ExitCode),
 
 		code_info__generate_resume_point(ResumePoint, ResumeCode),
 		{ code_info__resume_point_vars(ResumePoint, ResumeVarList) },
 		{ set__list_to_set(ResumeVarList, ResumeVars) },
 		code_info__set_forward_live_vars(ResumeVars),
-		trace__generate_external_event_code(fail, TraceInfo, _, _,
-			TraceFailCode),
+			% XXX A context that gives the end of the procedure
+			% definition would be better than BodyContext.
+		trace__generate_external_event_code(fail, TraceInfo,
+			BodyContext, _, _, TraceFailCode),
 		{ TraceSlotInfo = trace_slot_info(_, _, yes(_)) ->
 			DiscardTraceTicketCode = node([
 				discard_ticket - "discard retry ticket"
@@ -462,7 +478,7 @@
 		code_gen__generate_entry(model_non, Goal, ResumePoint,
 			FrameInfo, EntryCode),
 		code_gen__generate_exit(model_non, FrameInfo, TraceSlotInfo,
-			_, ExitCode),
+			BodyContext, _, ExitCode),
 		{ Code =
 			tree(EntryCode,
 			tree(BodyCode,
@@ -495,8 +511,8 @@
 	resume_point_info::in, frame_info::out, code_tree::out,
 	code_info::in, code_info::out) is det.
 
-code_gen__generate_entry(CodeModel, Goal, OutsideResumePoint,
-		FrameInfo, EntryCode) -->
+code_gen__generate_entry(CodeModel, Goal, OutsideResumePoint, FrameInfo,
+		EntryCode) -->
 	code_info__get_stack_slots(StackSlots),
 	code_info__get_varset(VarSet),
 	{ code_aux__explain_stack_slots(StackSlots, VarSet, SlotsComment) },
@@ -639,10 +655,10 @@
 	% we need only #undef a macro defined by the procedure prologue.
 
 :- pred code_gen__generate_exit(code_model::in, frame_info::in,
-	trace_slot_info::in, code_tree::out, code_tree::out,
+	trace_slot_info::in, prog_context::in, code_tree::out, code_tree::out,
 	code_info::in, code_info::out) is det.
 
-code_gen__generate_exit(CodeModel, FrameInfo, TraceSlotInfo,
+code_gen__generate_exit(CodeModel, FrameInfo, TraceSlotInfo, BodyContext,
 		RestoreDeallocCode, ExitCode) -->
 	{ StartComment = node([
 		comment("Start of procedure epilogue") - ""
@@ -716,8 +732,11 @@
 
 		code_info__get_maybe_trace_info(MaybeTraceInfo),
 		( { MaybeTraceInfo = yes(TraceInfo) } ->
+				% XXX A context that gives the end of the
+				% procedure definition would be better than
+				% CallContext.
 			trace__generate_external_event_code(exit, TraceInfo,
-				_, TypeInfoDatas, TraceExitCode),
+				BodyContext, _, TypeInfoDatas, TraceExitCode),
 			{ map__values(TypeInfoDatas, TypeInfoLocnSets) },
 			{ FindBaseLvals = lambda([Lval::out] is nondet, (
 				list__member(LocnSet, TypeInfoLocnSets),
@@ -957,13 +976,12 @@
 		set__insert(LiveVals0, stackvar(StackLoc), LiveVals1),
 		Instrn = livevals(LiveVals1)
         ;
-		Instrn0 = call(Target, ReturnLabel, LiveVals0, CM)
+		Instrn0 = call(Target, ReturnLabel, LiveVals0, Context, CM)
 	->
 		map__init(Empty),
-		Instrn  = call(Target, ReturnLabel, 
-			[live_lvalue(direct(stackvar(StackLoc)),
-				succip, Empty) |
-			LiveVals0], CM)
+		LiveVals  = [live_lvalue(direct(stackvar(StackLoc)),
+				succip, Empty) | LiveVals0],
+		Instrn = call(Target, ReturnLabel, LiveVals, Context, CM)
 	;
 		Instrn = Instrn0
 	),
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.242
diff -u -b -r1.242 code_info.m
--- code_info.m	1999/10/08 02:55:23	1.242
+++ code_info.m	1999/10/10 08:02:11
@@ -655,13 +655,9 @@
 :- pred code_info__succip_is_used(code_info, code_info).
 :- mode code_info__succip_is_used(in, out) is det.
 
-:- pred code_info__add_trace_layout_for_label(label, layout_label_info,
-	code_info, code_info).
-:- mode code_info__add_trace_layout_for_label(in, in, in, out) is det.
-
-:- pred code_info__add_gc_layout_for_label(label, layout_label_info,
-	code_info, code_info).
-:- mode code_info__add_gc_layout_for_label(in, in, in, out) is det.
+:- pred code_info__add_trace_layout_for_label(label, term__context,
+	layout_label_info, code_info, code_info).
+:- mode code_info__add_trace_layout_for_label(in, in, in, in, out) is det.
 
 :- pred code_info__add_non_common_static_data(comp_gen_c_data,
 	code_info, code_info).
@@ -671,6 +667,10 @@
 
 :- implementation.
 
+:- pred code_info__add_resume_layout_for_label(label, layout_label_info,
+	code_info, code_info).
+:- mode code_info__add_resume_layout_for_label(in, in, in, out) is det.
+
 code_info__get_stack_slots(StackSlots, CI, CI) :-
 	code_info__get_exprn_info(ExprnInfo, CI, _),
 	code_exprn__get_stack_slots(StackSlots, ExprnInfo, _).
@@ -835,36 +835,38 @@
 code_info__succip_is_used -->
 	code_info__set_succip_used(yes).
 
-code_info__add_trace_layout_for_label(Label, LayoutInfo) -->
+code_info__add_trace_layout_for_label(Label, Context, LayoutInfo) -->
 	code_info__get_layout_info(Internals0),
+	{ Exec = yes(Context - LayoutInfo) },
 	{ map__search(Internals0, Label, Internal0) ->
-		Internal0 = internal_layout_info(Exec0, Agc),
+		Internal0 = internal_layout_info(Exec0, Resume, Return),
 		( Exec0 = no ->
 			true
 		;
 			error("adding trace layout for already known label")
 		),
-		Internal = internal_layout_info(yes(LayoutInfo), Agc),
+		Internal = internal_layout_info(Exec, Resume, Return),
 		map__set(Internals0, Label, Internal, Internals)
 	;
-		Internal = internal_layout_info(yes(LayoutInfo), no),
+		Internal = internal_layout_info(Exec, no, no),
 		map__det_insert(Internals0, Label, Internal, Internals)
 	},
 	code_info__set_layout_info(Internals).
 
-code_info__add_gc_layout_for_label(Label, LayoutInfo) -->
+code_info__add_resume_layout_for_label(Label, LayoutInfo) -->
 	code_info__get_layout_info(Internals0),
+	{ Resume = yes(LayoutInfo) },
 	{ map__search(Internals0, Label, Internal0) ->
-		Internal0 = internal_layout_info(Exec, Agc0),
-		( Agc0 = no ->
+		Internal0 = internal_layout_info(Exec, Resume0, Return),
+		( Resume0 = no ->
 			true
 		;
 			error("adding gc layout for already known label")
 		),
-		Internal = internal_layout_info(Exec, yes(LayoutInfo)),
+		Internal = internal_layout_info(Exec, Resume, Return),
 		map__set(Internals0, Label, Internal, Internals)
 	;
-		Internal = internal_layout_info(no, yes(LayoutInfo)),
+		Internal = internal_layout_info(no, Resume, no),
 		map__det_insert(Internals0, Label, Internal, Internals)
 	},
 	code_info__set_layout_info(Internals).
@@ -3269,7 +3271,7 @@
 		code_info__get_module_info(ModuleInfo),
 		{ continuation_info__generate_resume_layout(ResumeMap,
 			Temps, InstMap, ProcInfo, ModuleInfo, Layout) },
-		code_info__add_gc_layout_for_label(Label, Layout)
+		code_info__add_resume_layout_for_label(Label, Layout)
 	;
 		[]
 	).
Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.27
diff -u -b -r1.27 continuation_info.m
--- continuation_info.m	1999/09/17 05:57:50	1.27
+++ continuation_info.m	1999/10/15 10:22:52
@@ -53,7 +53,7 @@
 
 :- import_module llds, hlds_module, hlds_pred, prog_data.
 :- import_module (inst), instmap, trace, globals.
-:- import_module std_util, bool, list, assoc_list, set, map.
+:- import_module bool, std_util, list, assoc_list, set, map.
 
 	%
 	% Information for any procedure, includes information about the
@@ -89,11 +89,13 @@
 	%
 	% Information for an internal label.
 	%
-	% There are two ways for the compiler to generate labels for
+	% There are three ways for the compiler to generate labels for
 	% which layouts may be required:
 	%
-	% (a) as the label associated with a trace port, and
-	% (b) as the return label of some kind of call (plain, method or h-o).
+	% (a) as the label associated with a trace port,
+	% (b) as the label associated with resume point that gets stored
+	%     as a redoip in a nondet stack frame, and
+	% (c) as the return label of some kind of call (plain, method or h-o).
 	%
 	% Label optimizations may redirect a call return away from the
 	% originally generated label to another label, possibly one
@@ -109,12 +111,13 @@
 	%   Even for these, we need only the pointer to the procedure layout
 	%   info; we do not need any information about variables.
 	%
-	% - For accurate gc, we are interested only in call return labels.
-	%   We need to know about all the variables that can be accessed
-	%   after the label; this is the intersection of all the variables
-	%   denoted as live in the call instructions. (Variables which
-	%   are not in the intersection are not guaranteed to have a
-	%   meaningful value on all execution paths that lead to the label.)
+	% - For accurate gc, we are interested only in resume point labels
+	%   and call return labels. We need to know about all the variables
+	%   that can be accessed after the label; this is the intersection of
+	%   all the variables denoted as live in the respective labels.
+	%   (Variables which are not in the intersection are not guaranteed
+	%   to have a meaningful value on all execution paths that lead to the
+	%   label.)
 	%
 	% - For execution tracing, our primary interest is in trace port
 	%   labels. At these labels we only want info about named variables,
@@ -133,11 +136,24 @@
 	% For labels which correspond to a trace port (part (a) above),
 	% we record information in the first field. Since trace.m generates
 	% a unique label for each trace port, this field is never updated
-	% once it is set in pass 2. For labels which correspond to a call
-	% return, we record information in the second field during pass 4.
-	% Since a label can serve as the return label for more than once call,
-	% this field can be updated (by taking the intersection of the live
-	% variables) after it is set. Since a call may return to the label
+	% once it is set in pass 2.
+	%
+	% For labels which correspond to redoips (part (b) above), we record
+	% information in the second fied. Since code_info.m generates
+	% unique labels for each resumption point, this field is never updated
+	% once it is set in pass 2.
+	% 
+	% For labels which correspond to a call return (part (c) above),
+	% we record information in the third field during pass 4. If execution
+	% tracing is turned on, then jumpopt.m will not redirect call return
+	% addresses, and thus each label will correspond to at most one call
+	% return. If execution tracing is turned off, jumpopt.m may redirect
+	% call return addresses, which means that a label can serve as the
+	% return label for more than once call. In that case, XXXX
+	% this field can be updated after it is set. This updating requires
+	% taking the intersection of the live variables, and 
+	%
+	% Since a call may return to the label
 	% of an internal port, it is possible for both fields to be set.
 	% In this case, stack_layout.m will take the union of the relevant
 	% info. If neither field is set, then the label's layout is required
@@ -145,8 +161,15 @@
 	%
 :- type internal_layout_info
 	--->	internal_layout_info(
+			maybe(pair(prog_context, layout_label_info)),
 			maybe(layout_label_info),
-			maybe(layout_label_info)
+			maybe(return_layout_info)
+		).
+
+:- type return_layout_info
+	--->	return_layout_info(
+			list(pair(code_addr, prog_context)),
+			layout_label_info
 		).
 
 	%
@@ -279,6 +302,14 @@
 		ContInfo = ContInfo0
 	).
 
+:- type call_info
+	--->	call_info(
+			label,		% the return label
+			code_addr,	% the target of the call
+			list(liveinfo),	% what is live on return
+			term__context	% the position of the call in source
+		).
+
 	%
 	% Process the list of instructions for this proc, adding
 	% all internal label information to global_data.
@@ -293,11 +324,12 @@
 		% Get all the continuation info from the call instructions.
 	global_data_get_proc_layout(GlobalData0, PredProcId, ProcLayoutInfo0),
 	ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, F, G, Internals0),
-	GetCallLivevals = lambda([Instr::in, Pair::out] is semidet, (
-		Instr = call(_, label(Label), LiveInfo, _) - _Comment,
-		Pair = Label - LiveInfo
+	GetCallInfo = lambda([Instr::in, Call::out] is semidet, (
+		Instr = call(Target, label(ReturnLabel), LiveInfo, Context, _)
+			- _Comment,
+		Call = call_info(ReturnLabel, Target, LiveInfo, Context)
 	)),
-	list__filter_map(GetCallLivevals, Instructions, Calls),
+	list__filter_map(GetCallInfo, Instructions, Calls),
 
 		% Process the continuation label info.
 	list__foldl(continuation_info__process_continuation(WantReturnInfo),
@@ -313,16 +345,17 @@
 	% Collect the liveness information from a single return label
 	% and add it to the internals.
 	%
-:- pred continuation_info__process_continuation(bool::in,
-	pair(label, list(liveinfo))::in,
+:- pred continuation_info__process_continuation(bool::in, call_info::in,
 	proc_label_layout_info::in, proc_label_layout_info::out) is det.
 
-continuation_info__process_continuation(WantReturnInfo, Label - LiveInfoList,
+continuation_info__process_continuation(WantReturnInfo, CallInfo,
 		Internals0, Internals) :-
-	( map__search(Internals0, Label, Internal0) ->
-		Internal0 = internal_layout_info(Port0, Return0)
+	CallInfo = call_info(ReturnLabel, Target, LiveInfoList, Context),
+	( map__search(Internals0, ReturnLabel, Internal0) ->
+		Internal0 = internal_layout_info(Port0, Resume0, Return0)
 	;
 		Port0 = no,
+		Resume0 = no,
 		Return0 = no
 	),
 	( WantReturnInfo = yes ->
@@ -330,24 +363,33 @@
 			VarInfoSet, TypeInfoMap),
 		(
 			Return0 = no,
-			Return = yes(layout_label_info(VarInfoSet,
-				TypeInfoMap))
+			Layout = layout_label_info(VarInfoSet, TypeInfoMap),
+			ReturnInfo = return_layout_info([Target - Context],
+				Layout),
+			Return = yes(ReturnInfo)
 		;
 				% If a var is known to be dead
 				% on return from one call, it
 				% cannot be accessed on returning
 				% from the other calls that reach
 				% the same return address either.
-			Return0 = yes(layout_label_info(LV0, TV0)),
+			Return0 = yes(ReturnInfo0),
+			ReturnInfo0 = return_layout_info(TargetsContexts0,
+				Layout0),
+			Layout0 = layout_label_info(LV0, TV0),
 			set__intersect(LV0, VarInfoSet, LV),
 			map__intersect(set__intersect, TV0, TypeInfoMap, TV),
-			Return = yes(layout_label_info(LV, TV))
+			Layout = layout_label_info(LV, TV),
+			TargetContexts = [Target - Context | TargetsContexts0],
+			ReturnInfo = return_layout_info(TargetContexts,
+				Layout),
+			Return = yes(ReturnInfo)
 		)
 	;
 		Return = Return0
 	),
-	Internal = internal_layout_info(Port0, Return),
-	map__set(Internals0, Label, Internal, Internals).
+	Internal = internal_layout_info(Port0, Resume0, Return),
+	map__set(Internals0, ReturnLabel, Internal, Internals).
 
 :- pred continuation_info__convert_return_data(list(liveinfo)::in,
 	set(var_info)::out, map(tvar, set(layout_locn))::out) is det.
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.42
diff -u -b -r1.42 dupelim.m
--- dupelim.m	1999/08/24 08:51:56	1.42
+++ dupelim.m	1999/10/10 06:48:11
@@ -291,7 +291,7 @@
 		standardize_rval(Rval1, Rval),
 		Instr = assign(Lval, Rval)
 	;
-		Instr1 = call(_, _, _, _),
+		Instr1 = call(_, _, _, _, _),
 		Instr = Instr1
 	;
 		Instr1 = mkframe(_, _),
@@ -558,7 +558,7 @@
 		most_specific_rval(Rval1, Rval2, Rval),
 		Instr = assign(Lval, Rval)
 	;
-		Instr1 = call(_, _, _, _),
+		Instr1 = call(_, _, _, _, _),
 		Instr2 = Instr1,
 		Instr = Instr1
 	;
@@ -790,8 +790,8 @@
 		assign(Lval, Rval)) :-
 	dupelim__replace_labels_lval(Lval0, ReplMap, Lval),
 	dupelim__replace_labels_rval(Rval0, ReplMap, Rval).
-dupelim__replace_labels_instr(call(Target, Return0, LiveInfo, CM),
-		ReplMap, call(Target, Return, LiveInfo, CM)) :-
+dupelim__replace_labels_instr(call(Target, Return0, LiveInfo, Context, CM),
+		ReplMap, call(Target, Return, LiveInfo, Context, CM)) :-
 	dupelim__replace_labels_code_addr(Return0, ReplMap, Return).
 dupelim__replace_labels_instr(mkframe(NondetFrameInfo, Redoip0), ReplMap,
 		mkframe(NondetFrameInfo, Redoip)) :-
Index: compiler/frameopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/frameopt.m,v
retrieving revision 1.72
diff -u -b -r1.72 frameopt.m
--- frameopt.m	1998/07/29 08:53:02	1.72
+++ frameopt.m	1999/10/10 06:49:03
@@ -531,7 +531,7 @@
 			list__member(Instr, Instrs),
 			Instr = Uinstr - _,
 			(
-				Uinstr = call(_, _, _, _)
+				Uinstr = call(_, _, _, _, _)
 			;
 				Uinstr = mkframe(_, _)
 			;
@@ -660,7 +660,7 @@
 possible_targets(block(_, _, _), _) :-
 	error("block in possible_targets").
 possible_targets(assign(_, _), []).
-possible_targets(call(_, ReturnAddr, _, _), Labels) :-
+possible_targets(call(_, ReturnAddr, _, _, _), Labels) :-
 	( ReturnAddr = label(Label) ->
 		Labels = [Label]
 	;
@@ -718,7 +718,7 @@
 		list__member(Instr, Instrs),
 		Instr = Uinstr - _,
 		(
-			Uinstr = call(_, _, _, _)
+			Uinstr = call(_, _, _, _, _)
 		;
 			% Only may_call_mercury pragma_c's can clobber succip.
 			Uinstr = pragma_c(_, _, may_call_mercury, _, _)
@@ -1263,8 +1263,9 @@
 substitute_labels_instr(block(_, _, _), _, _) :-
 	error("block in substitute_labels_instr").
 substitute_labels_instr(assign(Lval, Rval), _, assign(Lval, Rval)).
-substitute_labels_instr(call(Target, ReturnAddr0, LiveInfo, Model), LabelMap,
-		call(Target, ReturnAddr, LiveInfo, Model)) :-
+substitute_labels_instr(call(Target, ReturnAddr0, LiveInfo, Context, Model),
+		LabelMap,
+		call(Target, ReturnAddr, LiveInfo, Context, Model)) :-
 	(
 		ReturnAddr0 = label(Label0),
 		assoc_list__search(LabelMap, Label0, Label)
Index: compiler/jumpopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/jumpopt.m,v
retrieving revision 1.48
diff -u -b -r1.48 jumpopt.m
--- jumpopt.m	1999/09/30 08:55:08	1.48
+++ jumpopt.m	1999/10/10 07:12:36
@@ -15,11 +15,16 @@
 :- interface.
 
 :- import_module llds.
-:- import_module list, bool.
+:- import_module list, set, bool.
 
 	% Take an instruction list and optimize jumps. This includes jumps
 	% implicit in procedure returns.
 	%
+	% The second argument gives the set of labels that have layout
+	% structures. This module will not optimize jumps to labels in this
+	% set, since this may interfere with the RTTI recorded for these
+	% labels.
+	%
 	% The three bool inputs should be
 	%
 	% - the value of the --optimize-fulljumps option,
@@ -32,9 +37,9 @@
 	% The bool output says whether the instruction sequence was modified
 	% by the optimization.
 
-:- pred jumpopt_main(list(instruction), bool, bool, bool,
+:- pred jumpopt_main(list(instruction), set(label), bool, bool, bool,
 	list(instruction), bool).
-:- mode jumpopt_main(in, in, in, in, out, out) is det.
+:- mode jumpopt_main(in, in, in, in, in, out, out) is det.
 
 %-----------------------------------------------------------------------------%
 
@@ -69,7 +74,8 @@
 % numbering, which can do a better job of optimizing this block, have
 % been applied.
 
-jumpopt_main(Instrs0, Blockopt, Recjump, MostlyDetTailCall, Instrs, Mod) :-
+jumpopt_main(Instrs0, LayoutLabels, Blockopt, Recjump, MostlyDetTailCall,
+		Instrs, Mod) :-
 	map__init(Instrmap0),
 	map__init(Lvalmap0),
 	map__init(Procmap0),
@@ -84,13 +90,13 @@
 	( MostlyDetTailCall = yes ->
 		opt_util__get_prologue(Instrs0, ProcLabel, _, _, _),
 		opt_util__new_label_no(Instrs0, 500, LabelNum),
-		MostlyDetTailCallInfo = yes(ProcLabel - LabelNum)
+		CheckedNondetTailCallInfo = yes(ProcLabel - LabelNum)
 	;
-		MostlyDetTailCallInfo = no
+		CheckedNondetTailCallInfo = no
 	),
 	jumpopt__instr_list(Instrs0, comment(""), Instrmap, Blockmap, Lvalmap,
-		Procmap, Sdprocmap, Forkmap, Succmap, MostlyDetTailCallInfo,
-		_, Instrs1),
+		Procmap, Sdprocmap, Forkmap, Succmap, LayoutLabels,
+		CheckedNondetTailCallInfo, _, Instrs1),
 	opt_util__filter_out_bad_livevals(Instrs1, Instrs),
 	( Instrs = Instrs0 ->
 		Mod = no
@@ -208,22 +214,24 @@
 	% between the if-val and the goto.
 
 :- pred jumpopt__instr_list(list(instruction), instr, instrmap, tailmap,
-	lvalmap, tailmap, tailmap, tailmap, tailmap,
+	lvalmap, tailmap, tailmap, tailmap, tailmap, set(label),
 	maybe(pair(proc_label, int)), maybe(pair(proc_label, int)),
 	list(instruction)).
-:- mode jumpopt__instr_list(in, in, in, in, in, in, in, in, in, in, out, out)
-	is det.
+:- mode jumpopt__instr_list(in, in, in, in, in, in, in, in, in, in,
+	in, out, out) is det.
 
-jumpopt__instr_list([], _PrevInstr, _Instrmap, _Blockmap,
-		_Lvalmap, _Procmap, _Sdprocmap, _Forkmap, _Succmap,
-		MostlyDetTailCallInfo, MostlyDetTailCallInfo, []).
+jumpopt__instr_list([], _PrevInstr, _Instrmap, _Blockmap, _Lvalmap,
+		_Procmap, _Sdprocmap, _Forkmap, _Succmap, _LayoutLabels,
+		CheckedNondetTailCallInfo, CheckedNondetTailCallInfo, []).
 jumpopt__instr_list([Instr0 | Instrs0], PrevInstr, Instrmap, Blockmap,
-		Lvalmap, Procmap, Sdprocmap, Forkmap, Succmap,
-		MostlyDetTailCallInfo0, MostlyDetTailCallInfo, Instrs) :-
+		Lvalmap, Procmap, Sdprocmap, Forkmap, Succmap, LayoutLabels,
+		CheckedNondetTailCallInfo0, CheckedNondetTailCallInfo,
+		Instrs) :-
 	Instr0 = Uinstr0 - Comment0,
 	string__append(Comment0, " (redirected return)", Redirect),
 	(
-		Uinstr0 = call(Proc, label(RetLabel), GC, CallModel)
+		Uinstr0 = call(Proc, label(RetLabel), LiveInfos, Context,
+			CallModel)
 	->
 		(
 			% Look for det style tailcalls. We look for this
@@ -232,30 +240,33 @@
 			% into a det epilog.
 			( CallModel = det ; CallModel = semidet ),
 			map__search(Procmap, RetLabel, Between0),
-			PrevInstr = livevals(Livevals) 
+			PrevInstr = livevals(Livevals),
+			not set__member(RetLabel, LayoutLabels)
 		->
 			opt_util__filter_out_livevals(Between0, Between1),
 			list__append(Between1, [livevals(Livevals) - "",
 				goto(Proc) - Redirect], NewInstrs),
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			% Look for semidet style tailcalls.
 			CallModel = semidet,
 			map__search(Forkmap, RetLabel, Between),
-			PrevInstr = livevals(Livevals) 
+			PrevInstr = livevals(Livevals),
+			not set__member(RetLabel, LayoutLabels)
 		->
 			list__append(Between, [livevals(Livevals) - "",
 				goto(Proc) - Redirect], NewInstrs),
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			% Look for nondet style tailcalls which do not need
 			% a runtime check.
 			CallModel = nondet(unchecked_tail_call),
 			map__search(Succmap, RetLabel, BetweenIncl),
 			BetweenIncl = [livevals(_) - _, goto(_) - _],
-			PrevInstr = livevals(Livevals) 
+			PrevInstr = livevals(Livevals),
+			not set__member(RetLabel, LayoutLabels)
 		->
 			NewInstrs = [
 				assign(maxfr, lval(prevfr(lval(curfr))))
@@ -268,15 +279,17 @@
 				goto(Proc) - Redirect
 			],
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			% Look for nondet style tailcalls which do need
 			% a runtime check.
 			CallModel = nondet(checked_tail_call),
-			MostlyDetTailCallInfo0 = yes(ProcLabel - LabelNum0),
+			CheckedNondetTailCallInfo0 =
+				yes(ProcLabel - LabelNum0),
 			map__search(Succmap, RetLabel, BetweenIncl),
 			BetweenIncl = [livevals(_) - _, goto(_) - _],
-			PrevInstr = livevals(Livevals) 
+			PrevInstr = livevals(Livevals),
+			not set__member(RetLabel, LayoutLabels)
 		->
 			NewLabel = local(ProcLabel, LabelNum0),
 			NewInstrs = [
@@ -296,10 +309,11 @@
 			],
 			RemainInstrs = Instrs0,
 			LabelNum1 is LabelNum0 + 1,
-			MostlyDetTailCallInfo1 = yes(ProcLabel - LabelNum1)
+			CheckedNondetTailCallInfo1 = yes(ProcLabel - LabelNum1)
 		;
 			% Short circuit the return label if possible.
-			map__search(Instrmap, RetLabel, RetInstr)
+			map__search(Instrmap, RetLabel, RetInstr),
+			not set__member(RetLabel, LayoutLabels)
 		->
 			jumpopt__final_dest(RetLabel, RetInstr, Instrmap,
 				DestLabel, _DestInstr),
@@ -308,14 +322,15 @@
 				RemainInstrs = Instrs0
 			;
 				NewInstrs = [call(Proc, label(DestLabel),
-					GC, CallModel) - Redirect],
+					LiveInfos, Context, CallModel)
+					- Redirect],
 				RemainInstrs = Instrs0
 			),
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			NewInstrs = [Instr0],
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		)
 	;
 		Uinstr0 = goto(label(TargetLabel))
@@ -326,7 +341,7 @@
 		->
 			NewInstrs = [],
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			PrevInstr = if_val(_, label(IfTargetLabel)),
 			opt_util__is_this_label_next(IfTargetLabel, Instrs0, _)
@@ -339,7 +354,7 @@
 			% that would require altering the if_val instruction.
 			NewInstrs = [Instr0],
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			% Replace a jump to a det epilog with the epilog.
 			map__search(Procmap, TargetLabel, Between0)
@@ -348,7 +363,7 @@
 			list__append(Between, [goto(succip) - "shortcircuit"],
 				NewInstrs),
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			% Replace a jump to a semidet epilog with the epilog.
 			map__search(Sdprocmap, TargetLabel, Between0)
@@ -357,7 +372,7 @@
 			list__append(Between, [goto(succip) - "shortcircuit"],
 				NewInstrs),
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			% Replace a jump to a nondet epilog with the epilog.
 			map__search(Succmap, TargetLabel, BetweenIncl0)
@@ -365,7 +380,7 @@
 			jumpopt__adjust_livevals(PrevInstr, BetweenIncl0,
 				NewInstrs),
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			% Replace a jump to a non-epilog block with the
 			% block itself. These jumps are treated separately
@@ -397,9 +412,9 @@
 			map__delete(Blockmap, DestLabel, CrippledBlockmap),
 			jumpopt__instr_list(AdjustedBlock, comment(""),
 				Instrmap, CrippledBlockmap, Lvalmap, Procmap,
-				Sdprocmap, Forkmap, Succmap,
-				MostlyDetTailCallInfo0,
-				MostlyDetTailCallInfo1, NewInstrs),
+				Sdprocmap, Forkmap, Succmap, LayoutLabels,
+				CheckedNondetTailCallInfo0,
+				CheckedNondetTailCallInfo1, NewInstrs),
 			RemainInstrs = Instrs0
 		;
 			% Short-circuit the goto.
@@ -431,17 +446,17 @@
 			;
 				NewInstrs = NewInstrs0
 			),
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			NewInstrs = [Instr0],
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		)
 	; Uinstr0 = computed_goto(Index, LabelList0) ->
 		% Short-circuit all the destination labels.
 		jumpopt__short_labels(LabelList0, Instrmap, LabelList),
 		RemainInstrs = Instrs0,
-		MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0,
+		CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0,
 		( LabelList = LabelList0 ->
 			NewInstrs = [Instr0]
 		;
@@ -497,7 +512,7 @@
 			% loop because each application of the transformation
 			% strictly reduces the size of the code.
 			RemainInstrs = [NewInstr | AfterGoto],
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			map__search(Instrmap, TargetLabel, TargetInstr)
 		->
@@ -562,17 +577,17 @@
 				NewInstrs = [Instr0],
 				RemainInstrs = Instrs0
 			),
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		;
 			NewInstrs = [Instr0],
 			RemainInstrs = Instrs0,
-			MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+			CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 		)
 	; Uinstr0 = assign(Lval, Rval0) ->
 		% Any labels mentioned in Rval0 should be short-circuited.
 		jumpopt__short_labels_rval(Rval0, Instrmap, Rval),
 		RemainInstrs = Instrs0,
-		MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0,
+		CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0,
 		( Rval = Rval0 ->
 			NewInstrs = [Instr0]
 		;
@@ -583,7 +598,7 @@
 	;
 		NewInstrs = [Instr0],
 		RemainInstrs = Instrs0,
-		MostlyDetTailCallInfo1 = MostlyDetTailCallInfo0
+		CheckedNondetTailCallInfo1 = CheckedNondetTailCallInfo0
 	),
 	( ( Uinstr0 = comment(_) ; NewInstrs = [] ) ->
 		NewPrevInstr = PrevInstr
@@ -591,8 +606,9 @@
 		NewPrevInstr = Uinstr0
 	),
 	jumpopt__instr_list(RemainInstrs, NewPrevInstr, Instrmap, Blockmap,
-		Lvalmap, Procmap, Sdprocmap, Forkmap, Succmap,
-		MostlyDetTailCallInfo1, MostlyDetTailCallInfo, Instrs9),
+		Lvalmap, Procmap, Sdprocmap, Forkmap, Succmap, LayoutLabels,
+		CheckedNondetTailCallInfo1, CheckedNondetTailCallInfo,
+		Instrs9),
 	list__append(NewInstrs, Instrs9, Instrs).
 
 % We avoid generating statements that redefine the value of a location
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.43
diff -u -b -r1.43 livemap.m
--- livemap.m	1999/08/24 08:51:59	1.43
+++ livemap.m	1999/10/10 06:49:21
@@ -154,7 +154,7 @@
 		Instrs = Instrs0,
 		DontValueNumber = DontValueNumber0
 	;
-		Uinstr0 = call(_, _, _, _),
+		Uinstr0 = call(_, _, _, _, _),
 		livemap__look_for_livevals(Instrs0, Instrs,
 			Livevals0, Livevals, "call", yes, _),
 		Livemap = Livemap0,
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.251
diff -u -b -r1.251 llds.m
--- llds.m	1999/10/08 02:55:30	1.251
+++ llds.m	1999/11/04 05:32:42
@@ -248,11 +248,13 @@
 			% Assign the value specified by rval to the location
 			% specified by lval.
 
-	;	call(code_addr, code_addr, list(liveinfo), call_model)
-			% call(Target, Continuation, _, _) is the same as
+	;	call(code_addr, code_addr, list(liveinfo), term__context,
+				call_model)
+			% call(Target, Continuation, _, _, _) is the same as
 			% succip = Continuation; goto(Target).
 			% The third argument is the live value info for the
-			% values live on return. The last gives the model
+			% values live on return. The fourth argument gives
+			% the context of the call. The last gives the model
 			% of the called procedure, and if it is nondet,
 			% says whether tail recursion elimination is
 			% potentially applicable to the call.
@@ -916,14 +918,23 @@
 	% from `.opt' files, the defining module's name is added as a
 	% qualifier to the label.
 :- type proc_label
-	--->	proc(module_name, pred_or_func, module_name, string,
-								int, proc_id)
-			% defining module, predicate/function,
-			% declaring module, name, arity, mode #
-	;	special_proc(module_name, string, module_name, string, int,
-								proc_id).
-			% defining module, pred name, type module,
-			% type name, type arity, mode #
+	--->	proc(
+			module_name,	% defining module
+			pred_or_func,
+			module_name,	% declaring module
+			string,		% name
+			int,		% arity
+			proc_id		% mode number
+		)
+			
+	;	special_proc(
+			module_name,	% defining module
+			string,		% pred name
+			module_name,	% type module
+			string,		% type name
+			int,		% type arity
+			proc_id		% mode number
+		).
 
 	% A tag (used in mkword, create and field expressions
 	% and in incr_hp instructions) is a small integer.
Index: compiler/llds_common.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_common.m,v
retrieving revision 1.23
diff -u -b -r1.23 llds_common.m
--- llds_common.m	1999/04/30 08:23:49	1.23
+++ llds_common.m	1999/10/10 06:49:33
@@ -174,7 +174,7 @@
 		llds_common__process_rval(Rval0, Rval, Info0, Info),
 		Instr = assign(Lval, Rval)
 	;
-		Instr0 = call(_, _, _, _),
+		Instr0 = call(_, _, _, _, _),
 		Instr = Instr0,
 		Info = Info0
 	;
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.129
diff -u -b -r1.129 llds_out.m
--- llds_out.m	1999/11/04 04:21:00	1.129
+++ llds_out.m	1999/11/04 05:33:09
@@ -1155,7 +1155,7 @@
 		:-
 	(
 		(
-			Instr = call(_, label(ContLabel), _, _)
+			Instr = call(_, label(ContLabel), _, _, _)
 		;
 			Instr = mkframe(_, label(ContLabel))
 		;
@@ -1259,7 +1259,7 @@
 output_instruction_decls(assign(Lval, Rval), DeclSet0, DeclSet) -->
 	output_lval_decls(Lval, "", "", 0, _, DeclSet0, DeclSet1),
 	output_rval_decls(Rval, "", "", 0, _, DeclSet1, DeclSet).
-output_instruction_decls(call(Target, ContLabel, _, _), DeclSet0, DeclSet) -->
+output_instruction_decls(call(Target, ContLabel, _,_,_), DeclSet0, DeclSet) -->
 	output_code_addr_decls(Target, "", "", 0, _, DeclSet0, DeclSet1),
 	output_code_addr_decls(ContLabel, "", "", 0, _, DeclSet1, DeclSet).
 output_instruction_decls(c_code(_), DeclSet, DeclSet) --> [].
@@ -1509,7 +1509,7 @@
 	output_rval_as_type(Rval, Type),
 	io__write_string(";\n").
 
-output_instruction(call(Target, ContLabel, LiveVals, _), ProfInfo) -->
+output_instruction(call(Target, ContLabel, LiveVals, _, _), ProfInfo) -->
 	{ ProfInfo = CallerLabel - _ },
 	output_call(Target, ContLabel, CallerLabel),
 	output_gc_livevals(LiveVals).
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.78
diff -u -b -r1.78 middle_rec.m
--- middle_rec.m	1999/08/13 01:43:06	1.78
+++ middle_rec.m	1999/10/10 07:27:26
@@ -320,7 +320,7 @@
 middle_rec__split_rec_code([], _, _) :-
 	error("did not find call in middle_rec__split_rec_code").
 middle_rec__split_rec_code([Instr0 | Instrs1], Before, After) :-
-	( Instr0 = call(_, _, _, _) - _ ->
+	( Instr0 = call(_, _, _, _, _) - _ ->
 		(
 			opt_util__skip_comments(Instrs1, Instrs2),
 			Instrs2 = [Instr2 | Instrs3],
@@ -397,7 +397,7 @@
 middle_rec__find_used_registers_instr(assign(Lval, Rval), Used0, Used) :-
 	middle_rec__find_used_registers_lval(Lval, Used0, Used1),
 	middle_rec__find_used_registers_rval(Rval, Used1, Used).
-middle_rec__find_used_registers_instr(call(_, _, _, _), Used, Used).
+middle_rec__find_used_registers_instr(call(_, _, _, _, _), Used, Used).
 middle_rec__find_used_registers_instr(mkframe(_, _), Used, Used).
 middle_rec__find_used_registers_instr(label(_), Used, Used).
 middle_rec__find_used_registers_instr(goto(_), Used, Used).
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.95
diff -u -b -r1.95 opt_debug.m
--- opt_debug.m	1999/08/24 08:52:03	1.95
+++ opt_debug.m	1999/10/10 07:27:54
@@ -294,7 +294,7 @@
 
 opt_debug__dump_vninstr(vn_livevals(_), Str) :-
 	string__append_list(["livevals(...)"], Str).
-opt_debug__dump_vninstr(vn_call(Proc, Ret, _, _), Str) :-
+opt_debug__dump_vninstr(vn_call(Proc, Ret, _, _, _), Str) :-
 	opt_debug__dump_code_addr(Proc, P_str),
 	opt_debug__dump_code_addr(Ret, R_str),
 	string__append_list(["call(", P_str, ", ", R_str, ")"], Str).
@@ -857,7 +857,7 @@
 	opt_debug__dump_lval(Lval, L_str),
 	opt_debug__dump_rval(Rval, R_str),
 	string__append_list(["assign(", L_str, ", ", R_str, ")"], Str).
-opt_debug__dump_instr(call(Proc, Ret, _, _), Str) :-
+opt_debug__dump_instr(call(Proc, Ret, _, _, _), Str) :-
 	opt_debug__dump_code_addr(Proc, P_str),
 	opt_debug__dump_code_addr(Ret, R_str),
 	string__append_list(["call(", P_str, ", ", R_str, ", ...)"], Str).
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.102
diff -u -b -r1.102 opt_util.m
--- opt_util.m	1999/08/24 08:52:03	1.102
+++ opt_util.m	1999/10/10 06:52:49
@@ -769,7 +769,7 @@
 			opt_util__block_refers_stackvars(Instrs0, Need)
 		)
 	;
-		Uinstr0 = call(_, _, _, _),
+		Uinstr0 = call(_, _, _, _, _),
 		Need = no
 	;
 		Uinstr0 = mkframe(_, _),
@@ -973,7 +973,7 @@
 opt_util__can_instr_branch_away(livevals(_), no).
 opt_util__can_instr_branch_away(block(_, _, _), yes).
 opt_util__can_instr_branch_away(assign(_, _), no).
-opt_util__can_instr_branch_away(call(_, _, _, _), yes).
+opt_util__can_instr_branch_away(call(_, _, _, _, _), yes).
 opt_util__can_instr_branch_away(mkframe(_, _), no).
 opt_util__can_instr_branch_away(label(_), no).
 opt_util__can_instr_branch_away(goto(_), yes).
@@ -1035,7 +1035,7 @@
 opt_util__can_instr_fall_through(block(_, _, Instrs), FallThrough) :-
 	opt_util__can_block_fall_through(Instrs, FallThrough).
 opt_util__can_instr_fall_through(assign(_, _), yes).
-opt_util__can_instr_fall_through(call(_, _, _, _), no).
+opt_util__can_instr_fall_through(call(_, _, _, _, _), no).
 opt_util__can_instr_fall_through(mkframe(_, _), yes).
 opt_util__can_instr_fall_through(label(_), yes).
 opt_util__can_instr_fall_through(goto(_), no).
@@ -1079,7 +1079,7 @@
 opt_util__can_use_livevals(livevals(_), no).
 opt_util__can_use_livevals(block(_, _, _), no).
 opt_util__can_use_livevals(assign(_, _), no).
-opt_util__can_use_livevals(call(_, _, _, _), yes).
+opt_util__can_use_livevals(call(_, _, _, _, _), yes).
 opt_util__can_use_livevals(mkframe(_, _), no).
 opt_util__can_use_livevals(label(_), no).
 opt_util__can_use_livevals(goto(_), yes).
@@ -1140,7 +1140,7 @@
 opt_util__instr_labels_2(block(_, _, Instrs), Labels, CodeAddrs) :-
 	opt_util__instr_list_labels(Instrs, Labels, CodeAddrs).
 opt_util__instr_labels_2(assign(_,_), [], []).
-opt_util__instr_labels_2(call(Target, Ret, _, _), [], [Target, Ret]).
+opt_util__instr_labels_2(call(Target, Ret, _, _, _), [], [Target, Ret]).
 opt_util__instr_labels_2(mkframe(_, Addr), [], [Addr]).
 opt_util__instr_labels_2(label(_), [], []).
 opt_util__instr_labels_2(goto(Addr), [], [Addr]).
@@ -1178,7 +1178,7 @@
 opt_util__instr_rvals_and_lvals(block(_, _, Instrs), Labels, CodeAddrs) :-
 	opt_util__instr_list_rvals_and_lvals(Instrs, Labels, CodeAddrs).
 opt_util__instr_rvals_and_lvals(assign(Lval,Rval), [Rval], [Lval]).
-opt_util__instr_rvals_and_lvals(call(_, _, _, _), [], []).
+opt_util__instr_rvals_and_lvals(call(_, _, _, _, _), [], []).
 opt_util__instr_rvals_and_lvals(mkframe(_, _), [], []).
 opt_util__instr_rvals_and_lvals(label(_), [], []).
 opt_util__instr_rvals_and_lvals(goto(_), [], []).
@@ -1306,7 +1306,7 @@
 opt_util__count_temps_instr(assign(Lval, Rval), R0, R, F0, F) :-
 	opt_util__count_temps_lval(Lval, R0, R1, F0, F1),
 	opt_util__count_temps_rval(Rval, R1, R, F1, F).
-opt_util__count_temps_instr(call(_, _, _, _), R, R, F, F).
+opt_util__count_temps_instr(call(_, _, _, _, _), R, R, F, F).
 opt_util__count_temps_instr(mkframe(_, _), R, R, F, F).
 opt_util__count_temps_instr(label(_), R, R, F, F).
 opt_util__count_temps_instr(goto(_), R, R, F, F).
Index: compiler/optimize.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/optimize.m,v
retrieving revision 1.18
diff -u -b -r1.18 optimize.m
--- optimize.m	1999/09/30 08:55:11	1.18
+++ optimize.m	1999/10/19 07:29:14
@@ -144,7 +144,7 @@
 		;
 			[]
 		),
-		{ jumpopt_main(Instrs1, FullJumpopt, Final,
+		{ jumpopt_main(Instrs1, LayoutLabelSet, FullJumpopt, Final,
 			CheckedNondetTailCalls, Instrs2, Mod1) },
 		( { Mod1 = yes } ->
 			opt_debug__msg(DebugOpt, "after jump optimization"),
@@ -261,8 +261,9 @@
 			;
 				[]
 			),
-			{ jumpopt_main(Instrs1, FullJumpopt, Final,
-				CheckedNondetTailCalls, Instrs2, Mod2) },
+			{ jumpopt_main(Instrs1, LayoutLabelSet, FullJumpopt,
+				Final, CheckedNondetTailCalls, Instrs2,
+				Mod2) },
 			( { Mod2 = yes } ->
 				opt_debug__msg(DebugOpt, "after jump optimization"),
 				opt_debug__dump_instrs(DebugOpt, Instrs2)
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.271
diff -u -b -r1.271 options.m
--- options.m	1999/11/06 05:03:50	1.271
+++ options.m	1999/11/09 08:21:23
@@ -208,6 +208,9 @@
 				% the predicates deciding interface typeinfo
 				% liveness, should go through there.
 		;	body_typeinfo_liveness
+	% Options for internal use only
+	% (setting these options to non-default values can result in
+	% programs that do not link, or programs that dump core)
 				% Generate unify and compare preds.  For
 				% measurement only. Code generated with
 				% this set to `no' is unlikely to
@@ -228,6 +231,11 @@
 				% off, then you're unlikely to be able
 				% to link.
 		;	type_ctor_functors
+				% Generate line number information in the RTTI
+				% when debugging is enabled. For measurement
+				% only -- if you turn this off, then the
+				% debugger may dereference garbage pointers.
+		;	rtti_line_numbers
 	% Code generation options
 		;	low_level_debug
 		;	trad_passes
@@ -541,6 +549,7 @@
 	type_ctor_info		-	bool(yes),
 	type_ctor_layout	-	bool(yes),
 	type_ctor_functors	-	bool(yes),
+	rtti_line_numbers	-	bool(yes),
 	highlevel_c		-	bool(no),
 	gcc_nested_functions	-	bool(no),
 	unboxed_float		-	bool(no)
@@ -894,6 +903,7 @@
 long_option("type-ctor-info",		type_ctor_info).
 long_option("type-ctor-layout",		type_ctor_layout).
 long_option("type-ctor-functors",	type_ctor_functors).
+long_option("rtti-line-numbers",	rtti_line_numbers).
 long_option("highlevel-C",		highlevel_c).
 long_option("highlevel-c",		highlevel_c).
 long_option("high-level-C",		highlevel_c).
@@ -1840,7 +1850,7 @@
 %		"(This option is not for general use.)",
 %		"\tGenerate the stack_layout structures required for",
 %		"\taccurate garbage collection.",
-%
+
 		% This is a developer only option.
 %		"--procid-stack-layout",
 %		"(This option is not for general use.)",
Index: compiler/pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.31
diff -u -b -r1.31 pragma_c_gen.m
--- pragma_c_gen.m	1999/10/01 20:17:32	1.31
+++ pragma_c_gen.m	1999/10/10 07:26:20
@@ -41,7 +41,7 @@
 :- import_module hlds_module, hlds_pred, call_gen, llds_out, trace, tree.
 :- import_module code_util.
 :- import_module options, globals.
-:- import_module bool, string, int, assoc_list, set, map, require.
+:- import_module bool, string, int, assoc_list, set, map, require, term.
 
 % The code we generate for an ordinary (model_det or model_semi) pragma_c_code
 % must be able to fit into the middle of a procedure, since such
@@ -628,10 +628,20 @@
 	code_info__maybe_save_ticket(UseTrail, SaveTicketCode, MaybeTicketSlot),
 	code_info__maybe_reset_ticket(MaybeTicketSlot, undo, RestoreTicketCode),
 
+	{ FirstContext = yes(FirstContextPrime) ->
+		ActualFirstContext = FirstContextPrime
+	;
+		term__context_init(ActualFirstContext)
+	},
 	trace__maybe_generate_pragma_event_code(nondet_pragma_first,
-		FirstTraceCode),
+		ActualFirstContext, FirstTraceCode),
+	{ LaterContext = yes(LaterContextPrime) ->
+		ActualLaterContext = LaterContextPrime
+	;
+		term__context_init(ActualLaterContext)
+	},
 	trace__maybe_generate_pragma_event_code(nondet_pragma_later,
-		LaterTraceCode),
+		ActualLaterContext, LaterTraceCode),
 
 	{ FirstDisjunctCode =
 		tree(SaveHeapCode,
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.36
diff -u -b -r1.36 stack_layout.m
--- stack_layout.m	1999/10/19 04:11:34	1.36
+++ stack_layout.m	1999/11/05 05:28:10
@@ -26,7 +26,7 @@
 % If the option basic_stack_layout is set, we generate a MR_Stack_Layout_Entry
 % for each procedure. This will be stored in the global variable whose name is
 %	mercury_data__layout__mercury__<proc_label>.
-% This structure will always contain the following information:
+% This structure will always contain stack tracing information:
 %
 %	code address		(Code *) - address of entry
 % 	succip stack location	(uint_least32_t) actually, type MR_Long_Lval
@@ -109,15 +109,16 @@
 %	mercury_data__layout__mercury__<proc_label>_i<label_number>.
 % This table has the following format:
 %
-%	procedure info		(Word *) - pointer to procedure stack layout
-% 	# of live data item	(void *) - an encoded representation of
+%	proc layout		(Word *) - pointer to the layout structure of
+%				the procedure containing this label
+% 	# of live data items	(Integer) - an encoded representation of
 %				the number of live data items at the label
 % 	live data types locns 	(void *) - pointer to an area of memory
 %				containing information about where the live
 %				data items are and what their types are
 % 	live data names	 	(MR_Var_Name *) - pointer to vector of
 %				MR_Var_Name structs giving the HLDS var numbers
-%				as well as the names of live data items.
+%				as well as the names of live data items
 %	type parameters		(MR_Long_Lval *) - pointer to vector of
 %			 	MR_Long_Lval giving the locations of the
 %				typeinfos for the type parameters that may
@@ -264,25 +265,26 @@
 	globals__lookup_bool_option(Globals, agc_stack_layout, AgcLayout),
 	globals__lookup_bool_option(Globals, trace_stack_layout, TraceLayout),
 	globals__lookup_bool_option(Globals, procid_stack_layout,
-		ProcInfoLayout),
+		ProcIdLayout),
 	globals__have_static_code_addresses(Globals, StaticCodeAddr),
 	set_bbbtree__init(LayoutLabels0),
 
 	map__init(StringMap0),
+	map__init(LabelTables0),
 	StringTable0 = string_table(StringMap0, [], 0),
-	LayoutInfo0 = stack_layout_info(ModuleName, CellCount, AgcLayout,
-		TraceLayout, ProcInfoLayout, StaticCodeAddr,
-		[], [], LayoutLabels0, [], StringTable0),
+	LayoutInfo0 = stack_layout_info(ModuleName, CellCount,
+		AgcLayout, TraceLayout, ProcIdLayout, StaticCodeAddr,
+		[], [], LayoutLabels0, [], StringTable0, LabelTables0),
 	stack_layout__lookup_string_in_table("", _, LayoutInfo0, LayoutInfo1),
 	stack_layout__lookup_string_in_table("<too many variables>", _,
 		LayoutInfo1, LayoutInfo2),
 	list__foldl(stack_layout__construct_layouts, ProcLayoutList,
 		LayoutInfo2, LayoutInfo3),
-	stack_layout__get_next_cell_number(ProcVectorCellNum,
-		LayoutInfo3, LayoutInfo),
-	LayoutInfo  = stack_layout_info(_, FinalCellCount, _, _, _, _,
-		ProcLayouts, InternalLayouts, LayoutLabels, ProcLayoutArgs,
-		StringTable),
+		% This version of the layout info structure is final in all
+		% respects except the cell count.
+	LayoutInfo3 = stack_layout_info(_, _, _, _, _, _, ProcLayouts,
+		InternalLayouts, LayoutLabels, ProcLayoutArgs,
+		StringTable, LabelTables),
 	StringTable = string_table(_, RevStringList, StringOffset),
 	list__reverse(RevStringList, StringList),
 	stack_layout__concat_string_list(StringList, StringOffset,
@@ -292,22 +294,38 @@
 		Exported = no,	% ignored; see linkage/2 in llds_out.m
 		list__length(ProcLayoutList, NumProcLayouts),
 		llds_out__sym_name_mangle(ModuleName, ModuleNameStr),
+		stack_layout__get_next_cell_number(ProcVectorCellNum,
+			LayoutInfo3, LayoutInfo4),
 		ProcLayoutVector = create(0, ProcLayoutArgs,
 			uniform(yes(data_ptr)), must_be_static, 
 			ProcVectorCellNum, "proc_layout_vector"),
+		globals__lookup_bool_option(Globals, rtti_line_numbers,
+			LineNumbers),
+		( LineNumbers = yes ->
+			EffLabelTables = LabelTables
+		;
+			map__init(EffLabelTables)
+		),
+		stack_layout__format_label_tables(EffLabelTables,
+			NumSourceFiles, SourceFileVectors,
+			LayoutInfo4, LayoutInfo),
 		Rvals = [yes(const(string_const(ModuleNameStr))),
 			yes(const(int_const(StringOffset))),
 			yes(const(multi_string_const(StringOffset,
 				ConcatStrings))),
 			yes(const(int_const(NumProcLayouts))),
-			yes(ProcLayoutVector)],
+			yes(ProcLayoutVector),
+			yes(const(int_const(NumSourceFiles))),
+			yes(SourceFileVectors)],
 		ModuleLayouts = comp_gen_c_data(ModuleName, module_layout,
 			Exported, Rvals, uniform(no), []),
 		StaticLayouts = [ModuleLayouts | InternalLayouts]
 	;
-		StaticLayouts = InternalLayouts
+		StaticLayouts = InternalLayouts,
+		LayoutInfo = LayoutInfo3
 	),
 	PossiblyDynamicLayouts = ProcLayouts,
+	stack_layout__get_cell_number(FinalCellCount, LayoutInfo, _),
 	module_info_set_cell_count(ModuleInfo0, FinalCellCount, ModuleInfo).
 
 %---------------------------------------------------------------------------%
@@ -347,9 +365,133 @@
 
 %---------------------------------------------------------------------------%
 
+:- pred stack_layout__format_label_tables(map(string, label_table)::in,
+	int::out, rval::out, stack_layout_info::in, stack_layout_info::out)
+	is det.
+
+stack_layout__format_label_tables(LabelTableMap, NumSourceFiles,
+		SourceFilesVector, LayoutInfo0, LayoutInfo) :-
+	map__to_assoc_list(LabelTableMap, LabelTableList),
+	list__length(LabelTableList, NumSourceFiles),
+	list__map_foldl(stack_layout__format_label_table, LabelTableList,
+		SourceFileRvals, LayoutInfo0, LayoutInfo1),
+	stack_layout__get_next_cell_number(SourceFileVectorCellNum,
+		LayoutInfo1, LayoutInfo),
+	SourceFilesVector = create(0, SourceFileRvals,
+		uniform(yes(data_ptr)), must_be_static, 
+		SourceFileVectorCellNum, "source_files_vector").
+
+:- pred stack_layout__format_label_table(pair(string, label_table)::in,
+	maybe(rval)::out, stack_layout_info::in, stack_layout_info::out) is det.
+
+stack_layout__format_label_table(FileName - LineNoMap, yes(SourceFileVector),
+		LayoutInfo0, LayoutInfo) :-
+		% This step should produce a list ordered on line numbers.
+	map__to_assoc_list(LineNoMap, LineNoList),
+		% And this step should preserve that order.
+	stack_layout__flatten_label_table(LineNoList, [], FlatLineNoList),
+	list__length(FlatLineNoList, VectorLength),
+	stack_layout__get_module_name(CurrentModule, LayoutInfo0, LayoutInfo1),
+
+	ProjectLineNos = lambda([LabelInfo::in, LineNoRval::out] is det, (
+		LabelInfo = LineNo - (_Label - _IsReturn),
+		LineNoRval = yes(const(int_const(LineNo)))
+	)),
+	ProjectLabels = lambda([LabelInfo::in, LabelRval::out] is det, (
+		LabelInfo = _LineNo - (Label - _IsReturn),
+		DataAddr = data_addr(CurrentModule, internal_layout(Label)),
+		LabelRval = yes(const(data_addr_const(DataAddr)))
+	)),
+%	ProjectCallees = lambda([LabelInfo::in, CalleeRval::out] is det, (
+%		LabelInfo = _LineNo - (_Label - IsReturn),
+%		(
+%			IsReturn = not_a_return,
+%			CalleeRval = yes(const(int_const(0)))
+%		;
+%			IsReturn = unknown_callee,
+%			CalleeRval = yes(const(int_const(1)))
+%		;
+%			IsReturn = known_callee(Label),
+%			code_util__extract_proc_label_from_label(Label,
+%				ProcLabel),
+%			(
+%				ProcLabel = proc(ModuleName, _, _, _, _, _)
+%			;
+%				ProcLabel = special_proc(ModuleName, _, _,
+%					_, _, _)
+%			),
+%			DataAddr = data_addr(ModuleName, proc_layout(Label)),
+%			CalleeRval = yes(const(data_addr_const(DataAddr)))
+%		)
+%	)),
+
+	list__map(ProjectLineNos, FlatLineNoList, LineNoRvals),
+	stack_layout__get_next_cell_number(LineNoVectorCellNum,
+		LayoutInfo1, LayoutInfo2),
+	LineNoVector = create(0, LineNoRvals,
+		uniform(yes(int_least16)), must_be_static, 
+		LineNoVectorCellNum, "line_number_vector"),
+
+	list__map(ProjectLabels, FlatLineNoList, LabelRvals),
+	stack_layout__get_next_cell_number(LabelsVectorCellNum,
+		LayoutInfo2, LayoutInfo3),
+	LabelsVector = create(0, LabelRvals,
+		uniform(yes(data_ptr)), must_be_static, 
+		LabelsVectorCellNum, "label_vector"),
+
+% We do not include the callees vector in the table because it makes references
+% to the proc layouts of procedures from other modules without knowing whether
+% those modules were compiled with debugging. This works only if all procedures
+% always have a proc layout structure, which we don't want to require yet.
+%
+%	list__map(ProjectCallees, FlatLineNoList, CalleeRvals),
+%	stack_layout__get_next_cell_number(CalleesVectorCellNum,
+%		LayoutInfo3, LayoutInfo4),
+%	CalleesVector = create(0, CalleeRvals,
+%		uniform(no), must_be_static, 
+%		CalleesVectorCellNum, "callee_vector"),
+
+	SourceFileRvals = [
+		yes(const(string_const(FileName))),
+		yes(const(int_const(VectorLength))),
+		yes(LineNoVector),
+		yes(LabelsVector)
+%		yes(CalleesVector)
+	],
+	stack_layout__get_next_cell_number(SourceFileVectorCellNum,
+		LayoutInfo3, LayoutInfo),
+	SourceFileVector = create(0, SourceFileRvals,
+		initial([1 - yes(string), 1 - yes(integer),
+			2 - yes(data_ptr)], none),
+		must_be_static, 
+		SourceFileVectorCellNum, "source_file_vector").
+
+:- pred stack_layout__flatten_label_table(
+	assoc_list(int, list(line_no_info))::in,
+	assoc_list(int, line_no_info)::in,
+	assoc_list(int, line_no_info)::out) is det.
+
+stack_layout__flatten_label_table([], RevList, List) :-
+	list__reverse(RevList, List).
+stack_layout__flatten_label_table([LineNo - LinesInfos | Lines],
+		RevList0, List) :-
+	list__foldl(stack_layout__add_line_no(LineNo), LinesInfos,
+		RevList0, RevList1),
+	stack_layout__flatten_label_table(Lines, RevList1, List).
+
+:- pred stack_layout__add_line_no(int::in, line_no_info::in,
+	assoc_list(int, line_no_info)::in,
+	assoc_list(int, line_no_info)::out) is det.
+
+stack_layout__add_line_no(LineNo, LineInfo, RevList0, RevList) :-
+	RevList = [LineNo - LineInfo | RevList0].
+
+%---------------------------------------------------------------------------%
+
 	% Construct the layouts that concern a single procedure:
 	% the procedure-specific layout and the layouts of the labels
-	% inside that procedure.
+	% inside that procedure. Also update the module-wide label table
+	% with the labels defined in this procedure.
 
 :- pred stack_layout__construct_layouts(proc_layout_info::in,
 	stack_layout_info::in, stack_layout_info::out) is det.
@@ -363,10 +505,99 @@
 		ForceProcIdLayout),
 	{ map__to_assoc_list(InternalMap, Internals) },
 	list__foldl(stack_layout__construct_internal_layout(EntryLabel),
-		Internals).
+		Internals),
+	list__foldl(stack_layout__update_label_table, Internals).
 
 %---------------------------------------------------------------------------%
 
+	% Add the given label to the module-wide label tables.
+
+:- pred stack_layout__update_label_table(pair(label, internal_layout_info)::in,
+	stack_layout_info::in, stack_layout_info::out) is det.
+
+stack_layout__update_label_table(Label - InternalInfo) -->
+	{ InternalInfo = internal_layout_info(Port, _, Return) },
+	(
+		{ Return = yes(return_layout_info(TargetsContexts, _)) },
+		{ stack_layout__find_valid_return_context(TargetsContexts,
+			Target, Context) }
+	->
+		{ Target = label(TargetLabel) ->
+			IsReturn = known_callee(TargetLabel)
+		;
+			IsReturn = unknown_callee
+		},
+		stack_layout__update_label_table_2(Label, Context, IsReturn)
+	;
+		{ Port = yes(Context - _) },
+		{ stack_layout__context_is_valid(Context) }
+	->
+		stack_layout__update_label_table_2(Label, Context,
+			not_a_return)
+	;
+		[]
+	).
+
+:- pred stack_layout__update_label_table_2(label::in, context::in,
+	is_label_return::in, stack_layout_info::in, stack_layout_info::out)
+	is det.
+
+stack_layout__update_label_table_2(Label, Context, IsReturn) -->
+	{ term__context_file(Context, File) },
+	{ term__context_line(Context, Line) },
+	stack_layout__get_label_tables(LabelTables0),
+	{ map__search(LabelTables0, File, LabelTable0) ->
+		( map__search(LabelTable0, Line, LineInfo0) ->
+			LineInfo = [Label - IsReturn | LineInfo0],
+			map__det_update(LabelTable0, Line, LineInfo,
+				LabelTable),
+			map__det_update(LabelTables0, File, LabelTable,
+				LabelTables)
+		;
+			LineInfo = [Label - IsReturn],
+			map__det_insert(LabelTable0, Line, LineInfo,
+				LabelTable),
+			map__det_update(LabelTables0, File, LabelTable,
+				LabelTables)
+		)
+	; File = "" ->
+			% We don't have a valid context for this label,
+			% so we don't enter it into any tables.
+		LabelTables = LabelTables0
+	;
+		map__init(LabelTable0),
+		LineInfo = [Label - IsReturn],
+		map__det_insert(LabelTable0, Line, LineInfo,
+			LabelTable),
+		map__det_insert(LabelTables0, File, LabelTable,
+			LabelTables)
+	},
+	stack_layout__set_label_tables(LabelTables).
+
+:- pred stack_layout__find_valid_return_context(
+	assoc_list(code_addr, prog_context)::in,
+	code_addr::out, prog_context::out) is semidet.
+
+stack_layout__find_valid_return_context([Target - Context | TargetContexts],
+		ValidTarget, ValidContext) :-
+	( stack_layout__context_is_valid(Context) ->
+		ValidTarget = Target,
+		ValidContext = Context
+	;
+		stack_layout__find_valid_return_context(TargetContexts,
+			ValidTarget, ValidContext)
+	).
+
+:- pred stack_layout__context_is_valid(prog_context::in) is semidet.
+
+stack_layout__context_is_valid(Context) :-
+	term__context_file(Context, File),
+	term__context_line(Context, Line),
+	File \= "",
+	Line > 0.
+
+%---------------------------------------------------------------------------%
+
 	% Construct a procedure-specific layout.
 
 :- pred stack_layout__construct_proc_layout(label::in, determinism::in,
@@ -568,15 +799,6 @@
 		proc_layout(EntryLabel)))) },
 	stack_layout__construct_internal_rvals(Internal, VarInfoRvals,
 		VarInfoRvalTypes),
-	% Reenable this code if you want label numbers in label layouts.
-	% { Label = local(_, LabelNum0) ->
-	% 	LabelNum = LabelNum0
-	% ;
-	% 	LabelNum = 0
-	% },
-	% { LabelNumRval = const(int_const(LabelNum)) },
-	% { LayoutRvals = [yes(EntryAddrRval), yes(LabelNumRval)
-	% 	| VarInfoRvals] }
 	{ LayoutRvals = [yes(EntryAddrRval) | VarInfoRvals] },
 	{ ArgTypes = initial([1 - no], VarInfoRvalTypes) },
 	{ CData = comp_gen_c_data(ModuleName, internal_layout(Label),
@@ -590,13 +812,23 @@
 	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__construct_internal_rvals(Internal, RvalList, ArgTypes) -->
-	{ Internal = internal_layout_info(Port, Return) },
+	{ Internal = internal_layout_info(Port, Resume, Return) },
 	{
 		Port = no,
 		set__init(PortLiveVarSet),
 		map__init(PortTypeVarMap)
 	;
-		Port = yes(layout_label_info(PortLiveVarSet, PortTypeVarMap))
+		Port = yes(_ - PortLayout),
+		PortLayout = layout_label_info(PortLiveVarSet, PortTypeVarMap)
+	},
+	{
+		Resume = no,
+		set__init(ResumeLiveVarSet),
+		map__init(ResumeTypeVarMap)
+	;
+		Resume = yes(ResumeLayout),
+		ResumeLayout = layout_label_info(ResumeLiveVarSet,
+			ResumeTypeVarMap)
 	},
 	stack_layout__get_agc_stack_layout(AgcStackLayout),
 	{
@@ -604,8 +836,9 @@
 		set__init(ReturnLiveVarSet),
 		map__init(ReturnTypeVarMap)
 	;
-		Return = yes(layout_label_info(ReturnLiveVarSet0,
-			ReturnTypeVarMap0)),
+		Return = yes(return_layout_info(_, ReturnLayout)),
+		ReturnLayout = layout_label_info(ReturnLiveVarSet0,
+			ReturnTypeVarMap0),
 		( AgcStackLayout = yes ->
 			ReturnLiveVarSet = ReturnLiveVarSet0,
 			ReturnTypeVarMap = ReturnTypeVarMap0
@@ -625,6 +858,7 @@
 	},
 	(
 		{ Port = no },
+		{ Resume = no },
 		{ Return = no }
 	->
 			% The -1 says that there is no info available
@@ -635,8 +869,11 @@
 		{ ArgTypes = initial([1 - yes(integer)], none) }
 	;
 			% XXX ignore differences in insts inside var_infos
-		{ set__union(PortLiveVarSet, ReturnLiveVarSet, LiveVarSet) },
-		{ map__union(set__intersect, PortTypeVarMap, ReturnTypeVarMap,
+		{ set__union(PortLiveVarSet, ResumeLiveVarSet, LiveVarSet0) },
+		{ set__union(LiveVarSet0, ReturnLiveVarSet, LiveVarSet) },
+		{ map__union(set__intersect, PortTypeVarMap, ResumeTypeVarMap,
+			TypeVarMap0) },
+		{ map__union(set__intersect, TypeVarMap0, ReturnTypeVarMap,
 			TypeVarMap) },
 		stack_layout__construct_livelval_rvals(LiveVarSet,
 			TypeVarMap, RvalList, ArgTypes)
@@ -1293,6 +1530,20 @@
 
 	% Access to the stack_layout data structure.
 
+	% The per-sourcefile label table maps line numbers to the list of
+	% labels that correspond to that line. Each label is accompanied
+	% by a flag that says whether the label is the return site of a call
+	% or not, and if it is, whether the called procedure is known.
+
+:- type is_label_return
+	--->	known_callee(label)
+	;	unknown_callee
+	;	not_a_return.
+
+:- type line_no_info == pair(label, is_label_return).
+
+:- type label_table == map(int, list(line_no_info)).
+
 :- type stack_layout_info 	--->
 	stack_layout_info(
 		module_name,	% module name
@@ -1302,14 +1553,18 @@
 		bool,		% generate procedure id layout info?
 		bool,		% have static code addresses?
 		list(comp_gen_c_data),	% generated proc layouts
-		list(comp_gen_c_data),	% generated label layouts
+		list(comp_gen_c_data),	% generated internal layouts
 		set_bbbtree(label),
 				% the set of labels (both entry and internal)
 				% with layouts
 		list(maybe(rval)),
 				% the list of proc_layouts in the module,
 				% represented as create args
-		string_table
+		string_table,
+		map(string, label_table)
+				% maps each filename that contributes labels
+				% to this module to a table describing those
+				% labels.
 	).
 
 :- pred stack_layout__get_module_name(module_name::out,
@@ -1342,76 +1597,89 @@
 :- pred stack_layout__get_string_table(string_table::out,
 	stack_layout_info::in, stack_layout_info::out) is det.
 
+:- pred stack_layout__get_label_tables(map(string, label_table)::out,
+	stack_layout_info::in, stack_layout_info::out) is det.
+
 stack_layout__get_module_name(A, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(A, _, _, _, _, _, _, _, _, _, _).
+	LayoutInfo = stack_layout_info(A, _, _, _, _, _, _, _, _, _, _, _).
 
 stack_layout__get_cell_number(B, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, B, _, _, _, _, _, _, _, _, _).
+	LayoutInfo = stack_layout_info(_, B, _, _, _, _, _, _, _, _, _, _).
 
 stack_layout__get_agc_stack_layout(C, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, C, _, _, _, _, _, _, _, _).
+	LayoutInfo = stack_layout_info(_, _, C, _, _, _, _, _, _, _, _, _).
 
 stack_layout__get_trace_stack_layout(D, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, _, D, _, _, _, _, _, _, _).
+	LayoutInfo = stack_layout_info(_, _, _, D, _, _, _, _, _, _, _, _).
 
 stack_layout__get_procid_stack_layout(E, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, _, _, E, _, _, _, _, _, _).
+	LayoutInfo = stack_layout_info(_, _, _, _, E, _, _, _, _, _, _, _).
 
 stack_layout__get_static_code_addresses(F, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, _, _, _, F, _, _, _, _, _).
+	LayoutInfo = stack_layout_info(_, _, _, _, _, F, _, _, _, _, _, _).
 
 stack_layout__get_proc_layout_data(G, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, _, _, _, _, G, _, _, _, _).
+	LayoutInfo = stack_layout_info(_, _, _, _, _, _, G, _, _, _, _, _).
 
 stack_layout__get_internal_layout_data(H, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, _, _, _, _, _, H, _, _, _).
+	LayoutInfo = stack_layout_info(_, _, _, _, _, _, _, H, _, _, _, _).
 
 stack_layout__get_label_set(I, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, _, _, _, _, _, _, I, _, _).
+	LayoutInfo = stack_layout_info(_, _, _, _, _, _, _, _, I, _, _, _).
 
 stack_layout__get_string_table(K, LayoutInfo, LayoutInfo) :-
-	LayoutInfo = stack_layout_info(_, _, _, _, _, _, _, _, _, _, K).
+	LayoutInfo = stack_layout_info(_, _, _, _, _, _, _, _, _, _, K, _).
+
+stack_layout__get_label_tables(L, LayoutInfo, LayoutInfo) :-
+	LayoutInfo = stack_layout_info(_, _, _, _, _, _, _, _, _, _, _, L).
 
 :- pred stack_layout__add_proc_layout_data(comp_gen_c_data::in, data_name::in,
 	label::in, stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__add_proc_layout_data(NewG, NewJ, NewI, LayoutInfo0, LayoutInfo) :-
-	LayoutInfo0 = stack_layout_info(A, B, C, D, E, F, G0, H, I0, J0, K),
+	LayoutInfo0 = stack_layout_info(A, B, C, D, E, F, G0, H, I0, J0, K, L),
 	G = [NewG | G0],
 	set_bbbtree__insert(I0, NewI, I),
 	J = [yes(const(data_addr_const(data_addr(A, NewJ)))) | J0],
-	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G , H, I , J , K).
+	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G , H, I , J , K, L).
 
-:- pred stack_layout__add_internal_layout_data(comp_gen_c_data::in, label::in,
-	stack_layout_info::in, stack_layout_info::out) is det.
+:- pred stack_layout__add_internal_layout_data(comp_gen_c_data::in,
+	label::in, stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__add_internal_layout_data(NewH, NewI, LayoutInfo0, LayoutInfo) :-
-	LayoutInfo0 = stack_layout_info(A, B, C, D, E, F, G, H0, I0, J, K),
+	LayoutInfo0 = stack_layout_info(A, B, C, D, E, F, G, H0, I0, J, K, L),
 	H = [NewH | H0],
 	set_bbbtree__insert(I0, NewI, I),
-	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G, H , I , J, K).
+	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G, H , I , J, K, L).
 
 :- pred stack_layout__get_next_cell_number(int::out,
 	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__get_next_cell_number(B, LayoutInfo0, LayoutInfo) :-
-	LayoutInfo0 = stack_layout_info(A, B0, C, D, E, F, G, H, I, J, K),
+	LayoutInfo0 = stack_layout_info(A, B0, C, D, E, F, G, H, I, J, K, L),
 	B is B0 + 1,
-	LayoutInfo  = stack_layout_info(A, B,  C, D, E, F, G, H, I, J, K).
+	LayoutInfo  = stack_layout_info(A, B,  C, D, E, F, G, H, I, J, K, L).
 
 :- pred stack_layout__set_cell_number(int::in,
 	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__set_cell_number(B, LayoutInfo0, LayoutInfo) :-
-	LayoutInfo0 = stack_layout_info(A, _, C, D, E, F, G, H, I, J, K),
-	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G, H, I, J, K).
+	LayoutInfo0 = stack_layout_info(A, _, C, D, E, F, G, H, I, J, K, L),
+	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G, H, I, J, K, L).
 
 :- pred stack_layout__set_string_table(string_table::in,
 	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__set_string_table(K, LayoutInfo0, LayoutInfo) :-
-	LayoutInfo0 = stack_layout_info(A, B, C, D, E, F, G, H, I, J, _),
-	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G, H, I, J, K).
+	LayoutInfo0 = stack_layout_info(A, B, C, D, E, F, G, H, I, J, _, L),
+	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G, H, I, J, K, L).
+
+:- pred stack_layout__set_label_tables(map(string, label_table)::in,
+	stack_layout_info::in, stack_layout_info::out) is det.
+
+stack_layout__set_label_tables(L, LayoutInfo0, LayoutInfo) :-
+	LayoutInfo0 = stack_layout_info(A, B, C, D, E, F, G, H, I, J, K, _),
+	LayoutInfo  = stack_layout_info(A, B, C, D, E, F, G, H, I, J, K, L).
 
 %---------------------------------------------------------------------------%
 
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.24
diff -u -b -r1.24 trace.m
--- trace.m	1999/10/08 02:55:42	1.24
+++ trace.m	1999/10/10 08:05:02
@@ -136,13 +136,14 @@
 	% If we are doing execution tracing, generate code for an trace event
 	% that represents leaving a negated goal (via success or failure).
 :- pred trace__maybe_generate_negated_event_code(hlds_goal::in,
-	negation_end_port::in, code_tree::out,
-	code_info::in, code_info::out) is det.
+	negation_end_port::in, code_tree::out, code_info::in, code_info::out)
+	is det.
 
 	% If we are doing execution tracing, generate code for a nondet
 	% pragma C code trace event.
 :- pred trace__maybe_generate_pragma_event_code(nondet_pragma_trace_port::in,
-	code_tree::out, code_info::in, code_info::out) is det.
+	prog_context::in, code_tree::out, code_info::in, code_info::out)
+	is det.
 
 	% Generate code for an external trace event.
 	% Besides the trace code, we return the label on which we have hung
@@ -150,8 +151,9 @@
 	% liveness information, since some of our callers also need this
 	% information.
 :- pred trace__generate_external_event_code(external_trace_port::in,
-	trace_info::in, label::out, map(tvar, set(layout_locn))::out,
-	code_tree::out, code_info::in, code_info::out) is det.
+	trace_info::in, prog_context::in, label::out,
+	map(tvar, set(layout_locn))::out, code_tree::out,
+	code_info::in, code_info::out) is det.
 
 	% If the trace level calls for redo events, generate code that pushes
 	% a temporary nondet stack frame whose redoip slot contains the
@@ -167,7 +169,7 @@
 
 :- import_module continuation_info, type_util, llds_out, tree, varset.
 :- import_module (inst), instmap, inst_match, mode_util, options.
-:- import_module list, bool, int, string, map, std_util, require.
+:- import_module list, bool, int, string, map, std_util, require, term.
 
 	% Information specific to a trace port.
 :- type trace_port_info
@@ -493,9 +495,10 @@
 			{ Code = empty }
 		;
 			{ goal_info_get_pre_deaths(GoalInfo, PreDeaths) },
+			{ goal_info_get_context(GoalInfo, Context) },
 			trace__generate_event_code(Port,
 				internal(Path, PreDeaths), TraceInfo,
-				_, _, Code)
+				Context, _, _, Code)
 		)
 	;
 		{ Code = empty }
@@ -517,13 +520,14 @@
 		},
 		{ Goal = _ - GoalInfo },
 		{ goal_info_get_goal_path(GoalInfo, Path) },
+		{ goal_info_get_context(GoalInfo, Context) },
 		trace__generate_event_code(Port, negation_end(Path),
-			TraceInfo, _, _, Code)
+			TraceInfo, Context, _, _, Code)
 	;
 		{ Code = empty }
 	).
 
-trace__maybe_generate_pragma_event_code(PragmaPort, Code) -->
+trace__maybe_generate_pragma_event_code(PragmaPort, Context, Code) -->
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
 	(
 		{ MaybeTraceInfo = yes(TraceInfo) },
@@ -531,23 +535,24 @@
 	->
 		{ trace__convert_nondet_pragma_port_type(PragmaPort, Port) },
 		trace__generate_event_code(Port, nondet_pragma, TraceInfo,
-			_, _, Code)
+			Context, _, _, Code)
 	;
 		{ Code = empty }
 	).
 
-trace__generate_external_event_code(ExternalPort, TraceInfo,
+trace__generate_external_event_code(ExternalPort, TraceInfo, Context,
 		Label, TvarDataMap, Code) -->
 	{ trace__convert_external_port_type(ExternalPort, Port) },
 	trace__generate_event_code(Port, external, TraceInfo,
-		Label, TvarDataMap, Code).
+		Context, Label, TvarDataMap, Code).
 
 :- pred trace__generate_event_code(trace_port::in, trace_port_info::in,
-	trace_info::in, label::out, map(tvar, set(layout_locn))::out,
-	code_tree::out, code_info::in, code_info::out) is det.
+	trace_info::in, prog_context::in, label::out,
+	map(tvar, set(layout_locn))::out, code_tree::out,
+	code_info::in, code_info::out) is det.
 
-trace__generate_event_code(Port, PortInfo, TraceInfo, Label, TvarDataMap,
-		Code) -->
+trace__generate_event_code(Port, PortInfo, TraceInfo, Context,
+		Label, TvarDataMap, Code) -->
 	(
 		{ Port = fail },
 		{ trace_info_get_maybe_redo_layout_slot(TraceInfo,
@@ -634,7 +639,7 @@
 			CallStmt)
 		}
 	),
-	code_info__add_trace_layout_for_label(Label, LayoutLabelInfo),
+	code_info__add_trace_layout_for_label(Label, Context, LayoutLabelInfo),
 	{
 	string__append_list([DeclStmt, SaveStmt, CallStmt, RestoreStmt,
 		GotoStmt], TraceStmt),
Index: compiler/value_number.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/value_number.m,v
retrieving revision 1.98
diff -u -b -r1.98 value_number.m
--- value_number.m	1999/07/10 07:19:55	1.98
+++ value_number.m	1999/10/10 07:17:37
@@ -1080,7 +1080,7 @@
 	;
 		Boundary = no
 	).
-value_number__boundary_instr(call(_, _, _, _), yes).
+value_number__boundary_instr(call(_, _, _, _, _), yes).
 value_number__boundary_instr(mkframe(_, _), yes).
 value_number__boundary_instr(label(_), yes).
 value_number__boundary_instr(goto(_), yes).
Index: compiler/vn_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_block.m,v
retrieving revision 1.59
diff -u -b -r1.59 vn_block.m
--- vn_block.m	1999/07/10 07:19:55	1.59
+++ vn_block.m	1999/10/10 07:15:08
@@ -237,11 +237,11 @@
 		Specials = LeftSpecials
 	),
 	set__insert_list(Liveset0, Specials, Liveset).
-vn_block__handle_instr(call(Proc, Return, Info, CallModel),
+vn_block__handle_instr(call(Proc, Return, Info, Context, CallModel),
 		Livemap, Params, VnTables0, VnTables, Liveset0, Liveset,
 		SeenIncr, SeenIncr, Tuple0, Tuple) :-
-	vn_block__new_ctrl_node(vn_call(Proc, Return, Info, CallModel), Livemap,
-		Params, VnTables0, VnTables,
+	vn_block__new_ctrl_node(vn_call(Proc, Return, Info, Context,
+		CallModel), Livemap, Params, VnTables0, VnTables,
 		Liveset0, Liveset, Tuple0, Tuple).
 vn_block__handle_instr(mkframe(NondetFrameInfo, Redoip), Livemap, Params,
 		VnTables0, VnTables, Liveset0, Liveset,
@@ -405,7 +405,7 @@
 		LabelNo = LabelNo0,
 		Parallels = []
 	;
-		VnInstr = vn_call(_, _, _, _),
+		VnInstr = vn_call(_, _, _, _, _),
 		vn_block__record_at_call(VnTables0, VnTables, Liveset0, Liveset,
 			FlushEntry0, FlushEntry),
 		LabelNo = LabelNo0,
@@ -897,7 +897,7 @@
 vn_block__is_ctrl_instr(livevals(_), yes).
 vn_block__is_ctrl_instr(block(_, _, _), no).
 vn_block__is_ctrl_instr(assign(_, _), no).
-vn_block__is_ctrl_instr(call(_, _, _, _), yes).
+vn_block__is_ctrl_instr(call(_, _, _, _, _), yes).
 vn_block__is_ctrl_instr(mkframe(_, _), yes).
 vn_block__is_ctrl_instr(label(_), yes).
 vn_block__is_ctrl_instr(goto(_), yes).
Index: compiler/vn_cost.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_cost.m,v
retrieving revision 1.37
diff -u -b -r1.37 vn_cost.m
--- vn_cost.m	1999/07/10 07:19:55	1.37
+++ vn_cost.m	1999/10/10 07:13:39
@@ -108,7 +108,7 @@
 			Cost is RvalCost + LvalCost + AssignCost
 		)
 	;
-		Uinstr = call(_, _, _, _),
+		Uinstr = call(_, _, _, _, _),
 		Cost = 0
 	;
 		Uinstr = mkframe(_, _),
Index: compiler/vn_filter.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_filter.m,v
retrieving revision 1.21
diff -u -b -r1.21 vn_filter.m
--- vn_filter.m	1999/04/30 06:20:00	1.21
+++ vn_filter.m	1999/10/10 07:14:18
@@ -135,7 +135,7 @@
 vn_filter__user_instr(block(_, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__user_instr(assign(_, Rval), yes(Rval)).
-vn_filter__user_instr(call(_, _, _, _), no).
+vn_filter__user_instr(call(_, _, _, _, _), no).
 vn_filter__user_instr(mkframe(_, _), no).
 vn_filter__user_instr(label(_), no).
 vn_filter__user_instr(goto(_), no).
@@ -181,7 +181,7 @@
 vn_filter__replace_in_user_instr(assign(Lval, Rval0), Temp, Defn,
 		assign(Lval, Rval)) :-
 	vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
-vn_filter__replace_in_user_instr(call(_, _, _, _), _, _, _) :-
+vn_filter__replace_in_user_instr(call(_, _, _, _, _), _, _, _) :-
 	error("non-user instruction in vn_filter__replace_in_user_instr").
 vn_filter__replace_in_user_instr(mkframe(_, _), _, _, _) :-
 	error("non-user instruction in vn_filter__replace_in_user_instr").
@@ -242,7 +242,7 @@
 vn_filter__defining_instr(block(_, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__defining_instr(assign(Lval, _), yes(Lval)).
-vn_filter__defining_instr(call(_, _, _, _), no).
+vn_filter__defining_instr(call(_, _, _, _, _), no).
 vn_filter__defining_instr(mkframe(_, _), no).
 vn_filter__defining_instr(label(_), no).
 vn_filter__defining_instr(goto(_), no).
@@ -288,7 +288,7 @@
 vn_filter__replace_in_defining_instr(assign(Lval0, Rval), Temp, Defn,
 		assign(Lval, Rval)) :-
 	vn_filter__replace_in_lval(Lval0, Temp, Defn, Lval).
-vn_filter__replace_in_defining_instr(call(_, _, _, _), _, _, _) :-
+vn_filter__replace_in_defining_instr(call(_, _, _, _, _), _, _, _) :-
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
 vn_filter__replace_in_defining_instr(mkframe(_, _), _, _, _) :-
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
Index: compiler/vn_flush.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_flush.m,v
retrieving revision 1.49
diff -u -b -r1.49 vn_flush.m
--- vn_flush.m	1999/07/10 07:19:56	1.49
+++ vn_flush.m	1999/10/10 07:15:33
@@ -185,10 +185,12 @@
 		Templocs = Templocs0,
 		Instrs = [livevals(Livevals) - ""]
 	;
-		Vn_instr = vn_call(ProcAddr, RetAddr, LiveInfo, CodeModel),
+		Vn_instr = vn_call(ProcAddr, RetAddr, LiveInfo,
+			Context, CodeModel),
 		VnTables = VnTables0,
 		Templocs = Templocs0,
-		Instrs = [call(ProcAddr, RetAddr, LiveInfo, CodeModel) - ""]
+		Instrs = [call(ProcAddr, RetAddr, LiveInfo,
+			Context, CodeModel) - ""]
 	;
 		Vn_instr = vn_mkframe(NondetFrameInfo, Redoip),
 		vn_util__rval_to_vn(const(code_addr_const(Redoip)), AddrVn,
Index: compiler/vn_order.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_order.m,v
retrieving revision 1.48
diff -u -b -r1.48 vn_order.m
--- vn_order.m	1999/04/30 06:20:05	1.48
+++ vn_order.m	1999/10/10 07:15:56
@@ -323,7 +323,7 @@
 			Predmap1 = Predmap0,
 			VnTables1 = VnTables0
 		;
-			Vn_instr = vn_call(_, _, _, _),
+			Vn_instr = vn_call(_, _, _, _, _),
 			Succmap1 = Succmap0,
 			Predmap1 = Predmap0,
 			VnTables1 = VnTables0
Index: compiler/vn_type.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_type.m,v
retrieving revision 1.41
diff -u -b -r1.41 vn_type.m
--- vn_type.m	1999/07/10 07:19:56	1.41
+++ vn_type.m	1999/10/10 07:13:10
@@ -70,8 +70,8 @@
 			;	node_ctrl(int).
 
 :- type vn_instr	--->	vn_livevals(lvalset)
-			;	vn_call(code_addr, code_addr,
-					list(liveinfo), call_model)
+			;	vn_call(code_addr, code_addr, list(liveinfo),
+					term__context, call_model)
 			;	vn_mkframe(nondet_frame_info, code_addr)
 			;	vn_label(label)
 			;	vn_goto(code_addr)
Index: compiler/vn_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_util.m,v
retrieving revision 1.66
diff -u -b -r1.66 vn_util.m
--- vn_util.m	1999/07/10 07:19:56	1.66
+++ vn_util.m	1999/10/10 07:16:00
@@ -1228,7 +1228,7 @@
 			VnInstr = vn_livevals(_),
 			VnTables1 = VnTables0
 		;
-			VnInstr = vn_call(_, _, _, _),
+			VnInstr = vn_call(_, _, _, _, _),
 			VnTables1 = VnTables0
 		;
 			VnInstr = vn_mkframe(_, _),
Index: compiler/vn_verify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_verify.m,v
retrieving revision 1.21
diff -u -b -r1.21 vn_verify.m
--- vn_verify.m	1999/07/10 07:19:56	1.21
+++ vn_verify.m	1999/10/10 07:13:26
@@ -295,7 +295,7 @@
 		set__delete(NoDeref2, lval(Lval), NoDeref),
 		vn_verify__tags_rval(Rval, NoDeref)
 	;
-		Instr = call(_, _, _, _),
+		Instr = call(_, _, _, _, _),
 		NoDeref = NoDeref0,
 		Tested = Tested0
 	;
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.191
diff -u -b -r1.191 user_guide.texi
--- user_guide.texi	1999/11/04 07:35:22	1.191
+++ user_guide.texi	1999/11/09 08:29:43
@@ -1771,7 +1771,7 @@
 This command will report an error if there is no stack trace
 information available about any ancestor.
 @sp 1
- at item up [@var{num}]
+ at item up [-d] [@var{num}]
 Sets the current environment to the stack frame
 of the @var{num}'th level ancestor of the current environment
 (the immediate caller is the first-level ancestor).
@@ -1784,7 +1784,12 @@
 or if there is no stack trace information about any of the ancestors
 between the current environment and the requested ancestor.
 @sp 1
- at item down [@var{num}]
+The option @samp{-d} or @samp{--detailed}
+specifies that for each ancestor call,
+the call's event number, sequence number and depth should also be printed
+if the call is to a procedure that is being execution traced.
+ at sp 1
+ at item down [-d] [@var{num}]
 Sets the current environment to the stack frame
 of the @var{num}'th level descendant of the current environment
 (the procedure called by the current environment
@@ -1794,8 +1799,13 @@
 @sp 1
 This command will report an error
 if there is no execution trace information about the requested descendant.
+ at sp 1
+The option @samp{-d} or @samp{--detailed}
+specifies that for each ancestor call,
+the call's event number, sequence number and depth should also be printed
+if the call is to a procedure that is being execution traced.
 @sp 1
- at item level [@var{num}]
+ at item level [-d] [@var{num}]
 Sets the current environment to the stack frame of the @var{num}'th
 level ancestor of the call to which the current event belongs.
 The zero'th ancestor is the call of the event itself.
@@ -1806,6 +1816,11 @@
 or if there is no stack trace information about any of the ancestors
 between the current environment and the requested ancestor.
 @sp 1
+The option @samp{-d} or @samp{--detailed}
+specifies that for each ancestor call,
+the call's event number, sequence number and depth should also be printed
+if the call is to a procedure that is being execution traced.
+ at sp 1
 @item current
 Prints the current event.
 This is useful if the details of the event,
@@ -1817,6 +1832,16 @@
 @subsection Breakpoint commands
 @sp 1
 @table @code
+ at item break [-PS] @var{filename}:@var{linenumber}
+Puts a break point on the specified line of the specified file,
+if there is an event or a call at that position.
+If the filename is omitted,
+it defaults to the filename from the context of the current event.
+ at sp 1
+The options @samp{-P} or @samp{--print}, and @samp{-S} or @samp{--stop}
+specify the action to be taken at the break point.
+ at sp 1
+By default, the initial state of the break point is @samp{stop}.
 @item break [-PSaei] @var{proc-spec}
 @c <module name> <predicate name> [<arity> [<mode> [<predfunc>]]]
 Puts a break point on the specified procedure.
@@ -1936,6 +1961,39 @@
 @sp 1
 @item scroll
 Reports whether user scroll control is enabled and what the window size is.
+ at sp 1
+ at item context none
+When reporting events or ancestor levels,
+does not print contexts (filename/line number pairs).
+ at sp 1
+ at item context before
+When reporting events or ancestor levels,
+prints contexts (filename/line number pairs)
+before the identification of the event or call to which they refer,
+on the same line.
+With long fully qualifiied predicate and function names,
+this may make the line wrap around.
+ at sp 1
+ at item context after
+When reporting events or ancestor levels,
+prints contexts (filename/line number pairs)
+after the identification of the event or call to which they refer,
+on the same line.
+With long fully qualifiied predicate and function names,
+this may make the line wrap around.
+ at sp 1
+ at item context prevline
+When reporting events or ancestor levels,
+prints contexts (filename/line number pairs) on a separate line
+before the identification of the event or call to which they refer.
+ at sp 1
+ at item context nextline
+When reporting events or ancestor levels,
+prints contexts (filename/line number pairs) on a separate line
+after the identification of the event or call to which they refer.
+ at sp 1
+ at item context nextline
+Reports where contexts are being printed.
 @sp 1
 @item alias @var{name} @var{command} [@var{command-parameter} ...]
 Introduces @var{name} as an alias
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.29
diff -u -b -r1.29 mercury_stack_layout.h
--- mercury_stack_layout.h	1999/10/18 06:53:47	1.29
+++ mercury_stack_layout.h	1999/11/04 06:11:24
@@ -238,13 +238,27 @@
 } MR_Var_Name;
 
 /*
-** The MR_slvs_var_count field should be set to a negative number
-** if there is no information about the variables live at the label.
+** This data structure describes the variables live at a given point.
+** The count of live variables is encoded; it gives separately the counts
+** of variables that have short and long location descriptions, or it may
+** say that there is no information about variables at this point (which is
+** very different from saying that there are no variables live at this point).
+** You can decode the count using the macros below.
+**
+** The last three fields are meaningful only if the MR_has_valid_var_count
+** macro returns true.
+**
+** The names array pointer may be NULL, in which case no information about
+** variable names is available.
+**
+** The type parameters array may also be NULL, but this means that there are
+** no type parameters in the types of the variables live at this point.
+**
+** For further information, see the top of compiler/stack_layout.m.
 */
 
 typedef	struct MR_Stack_Layout_Vars_Struct {
-	void			*MR_slvs_var_count;
-	/* the remaining fields are present only if MR_sll_var_count > 0 */
+	Integer			MR_slvs_var_count;
 	void			*MR_slvs_locns_types;
 	MR_Var_Name		*MR_slvs_names;
 	MR_Type_Param_Locns	*MR_slvs_tvars;
@@ -263,6 +277,7 @@
 		(((Integer) ((slvs)->MR_slvs_var_count)) & MR_SHORT_COUNT_MASK)
 #define	MR_all_desc_var_count(slvs)					    \
 		(MR_long_desc_var_count(slvs) + MR_short_desc_var_count(slvs))
+
 #define	MR_var_pti(slvs, i)						    \
 		(((MR_PseudoTypeInfo **) ((slvs)->MR_slvs_locns_types))[(i)])
 #define	MR_end_of_var_ptis(slvs)					    \
@@ -495,20 +510,9 @@
 
 typedef	struct MR_Stack_Layout_Label_Struct {
 	MR_Stack_Layout_Entry	*MR_sll_entry;
-#ifdef	MR_LABEL_STRUCTS_INCLUDE_NUMBER
-	Integer			MR_sll_label_num;
-#endif
 	MR_Stack_Layout_Vars	MR_sll_var_info;
 } MR_Stack_Layout_Label;
 
-#ifdef	MR_LABEL_STRUCTS_INCLUDE_NUMBER
-  #define	UNKNOWN_INTERNAL_LABEL_FIELD	Integer f2;
-  #define	UNKNOWN_INTERNAL_LABEL_NUMBER	(Integer) -1,
-#else
-  #define	UNKNOWN_INTERNAL_LABEL_FIELD
-  #define	UNKNOWN_INTERNAL_LABEL_NUMBER
-#endif
-
 /*
 ** Define a stack layout for an internal label.
 **
@@ -530,10 +534,9 @@
 ** live value information as well to these macros.
 */ 
 
-#define MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(l, e)			\
-	MR_Stack_Layout_Label mercury_data__layout__##l = {		\
-		&mercury_data__layout__##e,				\
-		UNKNOWN_INTERNAL_LABEL_NUMBER				\
+#define MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(label, entry) \
+	MR_Stack_Layout_Label mercury_data__layout__##label = {		\
+		&mercury_data__layout__##entry,				\
 		{							\
 			(void *) -1,	/* No info about live values */	\
 			NULL,						\
@@ -542,14 +545,14 @@
 		}							\
 	}
 
-#define MR_MAKE_INTERNAL_LAYOUT(e, n)					\
-	MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(e##_i##n, e)
+#define MR_MAKE_INTERNAL_LAYOUT(entry, labelnum)			\
+	MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(entry##_i##labelnum, entry)
 
 /*-------------------------------------------------------------------------*/
 /*
 ** Definitions for MR_Module_Layout
 **
-** The layout struct for a module contains two main components.
+** The layout struct for a module contains three main components.
 **
 ** The first is a string table, which contains strings referred to by other
 ** layout structures in the module (initially only the tables containing
@@ -557,14 +560,34 @@
 **
 ** The second is a table containing pointers to the proc layout structures
 ** of all the procedures in the module.
+**
+** The third component contains N tables if the module has labels corresponding
+** to contexts that refer to N filenames. For each filename, the table gives
+** the name of the file and the number of labels in that file in this module;
+** for each such label it gives its line number and its label layout struct.
+**
+** The corresponding elements of the label_lineno and label_layout arrays
+** refer to the same label. (The reason why they are not stored together
+** is space efficiency; adding a 16 bit field to a label layout structure would
+** require padding.) The labels are sorted on line number.
 */
 
+typedef struct MR_Module_File_Layout_Struct {
+	String			MR_mfl_filename;
+	Integer			MR_mfl_label_count;
+	/* the following fields point to arrays of size MR_mfl_label_count */
+	MR_int_least16_t	*MR_mfl_label_lineno;
+	MR_Stack_Layout_Label	**MR_mfl_label_layout;
+} MR_Module_File_Layout;
+
 typedef	struct MR_Module_Layout_Struct {
 	String			MR_ml_name;
 	Integer			MR_ml_string_table_size;
 	char			*MR_ml_string_table;
 	Integer			MR_ml_proc_count;
 	MR_Stack_Layout_Entry	**MR_ml_procs;
+	Integer			MR_ml_filename_count;
+	MR_Module_File_Layout	**MR_ml_module_file_layout;
 } MR_Module_Layout;
 
 #endif /* not MERCURY_STACK_LAYOUT_H */
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.32
diff -u -b -r1.32 mercury_stack_trace.c
--- mercury_stack_trace.c	1999/06/08 03:47:41	1.32
+++ mercury_stack_trace.c	1999/11/10 03:41:43
@@ -7,25 +7,26 @@
 /*
 ** mercury_stack_trace.c - implements stack traces.
 **
-** Main author: Tyson Dowd (trd).
+** Main authors: Tyson Dowd (trd), Zoltan Somogyi (zs).
 */
 
 #include "mercury_imp.h"
 #include "mercury_stack_trace.h"
 #include <stdio.h>
 
-static	void	MR_dump_stack_record_init(void);
+static	void	MR_dump_stack_record_init(bool);
 static	void	MR_dump_stack_record_frame(FILE *fp,
-			const MR_Stack_Layout_Entry *,
+			const MR_Stack_Layout_Label *,
 			Word *base_sp, Word *base_curfr, 
-			void (*print_stack_record)(
-				FILE *, const MR_Stack_Layout_Entry *, 
-				int, int, Word *, Word *));
+			MR_Print_Stack_Record print_stack_record);
 static	void	MR_dump_stack_record_flush(FILE *fp, 
-			void (*print_stack_record)(
-				FILE *, const MR_Stack_Layout_Entry *, 
-				int, int, Word *, Word *));
+			MR_Print_Stack_Record print_stack_record);
 
+static	void	MR_maybe_print_context(FILE *fp,
+			const char *filename, int lineno);
+static	void	MR_maybe_print_parent_context(FILE *fp, bool print_parent,
+			bool verbose, const char *filename, int lineno);
+
 /* see comments in mercury_stack_trace.h */
 Code *MR_stack_trace_bottom;
 Word *MR_nondet_stack_trace_bottom;
@@ -37,9 +38,9 @@
 #ifndef MR_STACK_TRACE
 	fprintf(stderr, "Stack dump not available in this grade.\n");
 #else
+
 	const MR_Internal		*label;
 	const MR_Stack_Layout_Label	*layout;
-	const MR_Stack_Layout_Entry	*entry_layout;
 	const char			*result;
 
 	fprintf(stderr, "Stack dump follows:\n");
@@ -50,10 +51,9 @@
 		fprintf(stderr, "internal label not found\n");
 	} else {
 		layout = label->i_layout;
-		entry_layout = layout->MR_sll_entry;
-		result = MR_dump_stack_from_layout(stderr, entry_layout,
+		result = MR_dump_stack_from_layout(stderr, layout,
 			det_stack_pointer, current_frame, include_trace_data,
-			&MR_dump_stack_record_print);
+			TRUE, &MR_dump_stack_record_print);
 
 		if (result != NULL) {
 			fprintf(stderr, "%s\n", result);
@@ -63,13 +63,14 @@
 }
 
 const char *
-MR_dump_stack_from_layout(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
+MR_dump_stack_from_layout(FILE *fp, const MR_Stack_Layout_Label *label_layout,
 	Word *det_stack_pointer, Word *current_frame, bool include_trace_data,
-	void (*print_stack_record)(FILE *, const MR_Stack_Layout_Entry *, 
-	int, int, Word *, Word *))
+	bool include_contexts, MR_Print_Stack_Record print_stack_record)
 {
 	MR_Stack_Walk_Step_Result	result;
-	const MR_Stack_Layout_Label	*return_label_layout;
+	const MR_Stack_Layout_Entry	*entry_layout;
+	const MR_Stack_Layout_Label	*cur_label_layout;
+	const MR_Stack_Layout_Label	*prev_label_layout;
 	const char			*problem;
 	Word				*stack_trace_sp;
 	Word				*stack_trace_curfr;
@@ -77,27 +78,34 @@
 	Word				*old_trace_curfr;
 
 	do_init_modules();
-	MR_dump_stack_record_init();
+	MR_dump_stack_record_init(include_contexts);
 
 	stack_trace_sp = det_stack_pointer;
 	stack_trace_curfr = current_frame;
 
+	cur_label_layout = label_layout;
+
 	do {
+		entry_layout = cur_label_layout->MR_sll_entry;
+		prev_label_layout = cur_label_layout;
+
 		old_trace_sp    = stack_trace_sp;
 		old_trace_curfr = stack_trace_curfr;
 
-		result = MR_stack_walk_step(entry_layout, &return_label_layout,
+		result = MR_stack_walk_step(entry_layout, &cur_label_layout,
 				&stack_trace_sp, &stack_trace_curfr, &problem);
 		if (result == STEP_ERROR_BEFORE) {
 			MR_dump_stack_record_flush(fp, print_stack_record);
 			return problem;
 		} else if (result == STEP_ERROR_AFTER) {
 			if (include_trace_data) {
-				MR_dump_stack_record_frame(fp, entry_layout,
+				MR_dump_stack_record_frame(fp,
+					prev_label_layout,
 					old_trace_sp, old_trace_curfr, 
 					print_stack_record);
 			} else {
-				MR_dump_stack_record_frame(fp, entry_layout,
+				MR_dump_stack_record_frame(fp,
+					prev_label_layout,
 					NULL, NULL, print_stack_record);
 			}
 
@@ -105,21 +113,17 @@
 			return problem;
 		} else {
 			if (include_trace_data) {
-				MR_dump_stack_record_frame(fp, entry_layout,
+				MR_dump_stack_record_frame(fp,
+					prev_label_layout,
 					old_trace_sp, old_trace_curfr, 
 					print_stack_record);
 			} else {
-				MR_dump_stack_record_frame(fp, entry_layout,
+				MR_dump_stack_record_frame(fp,
+					prev_label_layout,
 					NULL, NULL, print_stack_record);
 			}
 		}
-
-		if (return_label_layout == NULL) {
-			break;
-		}
-
-		entry_layout = return_label_layout->MR_sll_entry;
-	} while (TRUE); 
+	} while (cur_label_layout != NULL);
 
 	MR_dump_stack_record_flush(fp, print_stack_record);
 	return NULL;
@@ -142,9 +146,15 @@
 	do_init_modules();
 	*problem = NULL;
 	for (i = 0; i < ancestor_level && label_layout != NULL; i++) {
-		(void) MR_stack_walk_step(label_layout->MR_sll_entry,
+		result = MR_stack_walk_step(label_layout->MR_sll_entry,
 				&return_label_layout,
 				stack_trace_sp, stack_trace_curfr, problem);
+
+		if (result != STEP_OK) {
+			/* *problem has already been filled in */
+			return NULL;
+		}
+
 		label_layout = return_label_layout;
 	}
 
@@ -155,7 +165,6 @@
 	return label_layout;
 }
 
-
 MR_Stack_Walk_Step_Result
 MR_stack_walk_step(const MR_Stack_Layout_Entry *entry_layout,
 	const MR_Stack_Layout_Label **return_label_layout,
@@ -281,24 +290,40 @@
 static	int				prev_entry_start_level;
 static	Word				*prev_entry_base_sp;
 static	Word				*prev_entry_base_curfr;
+static	const char			*prev_entry_filename;
+static	int				prev_entry_linenumber;
+static	bool				prev_entry_context_mismatch;
 static	int				current_level;
+static	bool				contexts_enabled;
 
 static void
-MR_dump_stack_record_init(void)
+MR_dump_stack_record_init(bool include_contexts)
 {
 	prev_entry_layout = NULL;
 	prev_entry_layout_count = 0;
 	prev_entry_start_level = 0;
 	current_level = 0;
+	contexts_enabled = include_contexts;
 }
 
 static void
-MR_dump_stack_record_frame(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
-	Word *base_sp, Word *base_curfr, void (*print_stack_record)(
-		FILE *, const MR_Stack_Layout_Entry *, int, int, Word *, Word *))
+MR_dump_stack_record_frame(FILE *fp, const MR_Stack_Layout_Label *label_layout,
+	Word *base_sp, Word *base_curfr,
+	MR_Print_Stack_Record print_stack_record)
 {
+	const MR_Stack_Layout_Entry	*entry_layout;
+	const char			*filename;
+	int				linenumber;
 	bool	must_flush;
 
+	entry_layout = label_layout->MR_sll_entry;
+	if (! MR_find_context(label_layout, &filename, &linenumber)
+		|| ! contexts_enabled)
+	{
+		filename = "";
+		linenumber = 0;
+	}
+
 	must_flush = 
 		/*
 		** We cannot merge two calls if they are to different
@@ -328,28 +353,37 @@
 		prev_entry_start_level = current_level;
 		prev_entry_base_sp = base_sp;
 		prev_entry_base_curfr = base_curfr;
+		prev_entry_filename = filename;
+		prev_entry_linenumber = linenumber;
+		prev_entry_context_mismatch = FALSE;
 	} else {
 		prev_entry_layout_count++;
+		if (prev_entry_filename != filename
+			|| prev_entry_linenumber != linenumber)
+		{
+			prev_entry_context_mismatch = TRUE;
+		}
 	}
 
 	current_level++;
 }
 
 static void
-MR_dump_stack_record_flush(FILE *fp, void (*print_stack_record)(
-	FILE *, const MR_Stack_Layout_Entry *, int, int, Word *, Word *))
+MR_dump_stack_record_flush(FILE *fp, MR_Print_Stack_Record print_stack_record)
 {
 	if (prev_entry_layout != NULL) {
 		print_stack_record(fp, prev_entry_layout,
 			prev_entry_layout_count, prev_entry_start_level,
-			prev_entry_base_sp, prev_entry_base_curfr);
+			prev_entry_base_sp, prev_entry_base_curfr,
+			prev_entry_filename, prev_entry_linenumber,
+			prev_entry_context_mismatch);
 	}
 }
 
-
 void
 MR_dump_stack_record_print(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
-	int count, int start_level, Word *base_sp, Word *base_curfr)
+	int count, int start_level, Word *base_sp, Word *base_curfr,
+	const char *filename, int linenumber, bool context_mismatch)
 {
 	fprintf(fp, "%4d ", start_level);
 
@@ -364,26 +398,59 @@
 		** so we don't reserve space for the repeat counts.
 		*/
 	}
+
+	MR_print_call_trace_info(fp, entry_layout, base_sp, base_curfr);
+	MR_print_proc_id(fp, entry_layout);
+	if (strdiff(filename, "") && linenumber > 0) {
+		fprintf(fp, " (%s:%d%s)", filename, linenumber,
+			context_mismatch? " and others" : "");
+	}
 
-	MR_print_proc_id(fp, entry_layout, NULL, base_sp, base_curfr);
+	fprintf(fp, "\n");
 }
 
-void
-MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
-	const char *extra, Word *base_sp, Word *base_curfr)
+bool
+MR_find_context(const MR_Stack_Layout_Label *label, const char **fileptr,
+	int *lineptr)
 {
-	if (! MR_ENTRY_LAYOUT_HAS_PROC_ID(entry)) {
-		fatal_error("cannot print procedure id without layout");
+	const MR_Stack_Layout_Entry	*proc;
+	const MR_Module_Layout		*module;
+	const MR_Module_File_Layout	*file_layout;
+	int				i, j;
+
+	proc = label->MR_sll_entry;
+	if (! MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(proc)) {
+		return FALSE;
 	}
 
+	module = proc->MR_sle_module_layout;
+	for (i = 0; i < module->MR_ml_filename_count; i++) {
+		file_layout = module->MR_ml_module_file_layout[i];
+		for (j = 0; j < file_layout->MR_mfl_label_count; j++) {
+			if (file_layout->MR_mfl_label_layout[j] == label) {
+				*fileptr = file_layout->MR_mfl_filename;
+				*lineptr = file_layout->MR_mfl_label_lineno[j];
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+void
+MR_print_call_trace_info(FILE *fp, const MR_Stack_Layout_Entry *entry,
+	Word *base_sp, Word *base_curfr)
+{
+	bool	print_details;
+
 	if (base_sp != NULL && base_curfr != NULL) {
-		bool print_details = FALSE;
 		if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
 			Integer maybe_from_full =
 				entry->MR_sle_maybe_from_full;
 			if (maybe_from_full > 0) {
 				/*
-				** for procedures compiled with shallow
+				** For procedures compiled with shallow
 				** tracing, the details will be valid only
 				** if the value of MR_from_full saved in
 				** the appropriate stack slot was TRUE.
@@ -397,12 +464,15 @@
 				}
 			} else {
 				/*
-				** for procedures compiled with full tracing,
-				** always print out the details
+				** For procedures compiled with full tracing,
+				** we can always print out the details.
 				*/
 				print_details = TRUE;
 			}
+		} else {
+			print_details = FALSE;
 		}
+
 		if (print_details) {
 			if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
 				fprintf(fp, "%7lu %7lu %4lu ",
@@ -426,7 +496,15 @@
 			fprintf(fp, "%21s", "");
 		}
 	}
+}
 
+void
+MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry)
+{
+	if (! MR_ENTRY_LAYOUT_HAS_PROC_ID(entry)) {
+		fatal_error("cannot print procedure id without layout");
+	}
+
 	if (MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry)) {
 		fprintf(fp, "%s for %s:%s/%ld-%ld",
 			entry->MR_sle_comp.MR_comp_pred_name,
@@ -467,14 +545,109 @@
 	}
 
 	fprintf(fp, " (%s)", MR_detism_names[entry->MR_sle_detism]);
+}
 
-	if (extra != NULL) {
-		fprintf(fp, " %s\n", extra);
-	} else {
+void
+MR_print_proc_id_trace_and_context(FILE *fp, MR_Context_Position pos,
+	const MR_Stack_Layout_Entry *entry, Word *base_sp, Word *base_curfr,
+	const char *path, const char *filename, int lineno, bool print_parent, 
+	const char *parent_filename, int parent_lineno, int indent)
+{
+
+	switch (pos) {
+		case MR_CONTEXT_NOWHERE:
+			fprintf(fp, " ");
+			MR_print_call_trace_info(fp, entry,
+				base_sp, base_curfr);
+			MR_print_proc_id(fp, entry);
+			if (strlen(path) > 0) {
+				fprintf(fp, " %s", path);
+			}
 		fprintf(fp, "\n");
+			break;
+
+		case MR_CONTEXT_BEFORE:
+			MR_maybe_print_context(fp, filename, lineno);
+			MR_maybe_print_parent_context(fp, print_parent,
+				FALSE, parent_filename, parent_lineno);
+			fprintf(fp, " ");
+			MR_print_call_trace_info(fp, entry,
+				base_sp, base_curfr);
+			MR_print_proc_id(fp, entry);
+			if (strlen(path) > 0) {
+				fprintf(fp, " %s", path);
 	}
+			fprintf(fp, "\n");
+			break;
+
+		case MR_CONTEXT_AFTER:
+			fprintf(fp, " ");
+			MR_print_call_trace_info(fp, entry,
+				base_sp, base_curfr);
+			MR_print_proc_id(fp, entry);
+			if (strlen(path) > 0) {
+				fprintf(fp, " %s", path);
+			}
+			MR_maybe_print_context(fp, filename, lineno);
+			MR_maybe_print_parent_context(fp, print_parent,
+				FALSE, parent_filename, parent_lineno);
+			fprintf(fp, "\n");
+			break;
+
+		case MR_CONTEXT_PREVLINE:
+			MR_maybe_print_context(fp, filename, lineno);
+			MR_maybe_print_parent_context(fp, print_parent,
+				TRUE, parent_filename, parent_lineno);
+			fprintf(fp, "\n%*s ", indent, "");
+			MR_print_call_trace_info(fp, entry,
+				base_sp, base_curfr);
+			MR_print_proc_id(fp, entry);
+			if (strlen(path) > 0) {
+				fprintf(fp, " %s", path);
+			}
+			fprintf(fp, "\n");
+			break;
+
+		case MR_CONTEXT_NEXTLINE:
+			fprintf(fp, " ");
+			MR_print_call_trace_info(fp, entry,
+				base_sp, base_curfr);
+			MR_print_proc_id(fp, entry);
+			if (strlen(path) > 0) {
+				fprintf(fp, " %s", path);
+			}
+			fprintf(fp, "\n%*s", indent, "");
+			MR_maybe_print_context(fp, filename, lineno);
+			MR_maybe_print_parent_context(fp, print_parent,
+				TRUE, parent_filename, parent_lineno);
+			fprintf(fp, "\n");
+			break;
+
+		default:
+			fatal_error("invalid MR_Context_Position");
+	}
+}
+
+static void
+MR_maybe_print_context(FILE *fp, const char *filename, int lineno)
+{
+	if (strdiff(filename, "") && lineno != 0) {
+		fprintf(fp, " %s:%d", filename, lineno);
+	}
 }
 
+static void
+MR_maybe_print_parent_context(FILE *fp, bool print_parent, bool verbose,
+	const char *filename, int lineno)
+{
+	if (print_parent && strdiff(filename, "") && lineno != 0) {
+		if (verbose) {
+			fprintf(fp, " (from %s:%d)", filename, lineno);
+		} else {
+			fprintf(fp, " (%s:%d)", filename, lineno);
+		}
+	}
+}
 
 /*
 ** The different Mercury determinisms are internally represented by integers. 
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.18
diff -u -b -r1.18 mercury_stack_trace.h
--- mercury_stack_trace.h	1999/06/08 03:47:41	1.18
+++ mercury_stack_trace.h	1999/11/10 03:16:58
@@ -46,20 +46,27 @@
 /*
 ** MR_dump_stack_from_layout:
 **	This function does the same job and makes the same assumptions
-**	as MR_dump_stack, but instead of the succip, it takes the entry
-**	layout of the current procedure as input. It also takes a parameter
-**	that tells it where to put the stack dump. If the entire stack
-**	was printed successfully, the return value is NULL; otherwise,
-**	it is a string indicating why the dump was cut short.
+**	as MR_dump_stack, but instead of the succip, it takes the label
+**	layout of the current point in the current procedure as input.
+**	It also takes a parameter that tells it where to put the stack dump
+**	and flags that say whether to include execution trace data and/or
+**	line numbers.
+**
+**	If the entire stack was printed successfully, the return value is NULL;
+**	otherwise, it is a string indicating why the dump was cut short.
 */
 
+typedef	void		(*MR_Print_Stack_Record)(FILE *, 
+				const MR_Stack_Layout_Entry *, 
+				int, int, Word *, Word *,
+				const char *, int, bool);
+
 extern	const char	*MR_dump_stack_from_layout(FILE *fp,
-				const MR_Stack_Layout_Entry *entry_layout,
+				const MR_Stack_Layout_Label *label_layout,
 				Word *det_stack_pointer, Word *current_frame,
 				bool include_trace_data,
-				void (*print_stack_record)(FILE *, 
-					const MR_Stack_Layout_Entry *, 
-					int, int, Word *, Word *));
+				bool include_contexts,
+				MR_Print_Stack_Record print_stack_record);
 
 /*
 ** MR_dump_nondet_stack_from_layout:
@@ -143,29 +150,69 @@
 ** the names that are usually used to denote determinisms.
 */
 
-extern const char * MR_detism_names[];
+extern	const char *MR_detism_names[];
 
 /*
+** MR_find_context attempts to look up the file name and line number
+** corresponding to a label identified by its layout structure. If successful,
+** it fills in *fileptr and *lineptr accordingly, and returns TRUE; otherwise,
+** it returns FALSE.
+*/
+
+extern	bool	MR_find_context(const MR_Stack_Layout_Label *label,
+			const char **fileptr, int *lineptr);
+
+/*
+** If the procedure has trace layout information and the relevant one of
+** base_sp and base_curfr is not NULL, MR_print_call_trace_info prints
+** the call event number, call sequence number and call depth of the call
+** stored in the stack frame of the procedure.
+*/
+
+extern	void	MR_print_call_trace_info(FILE *fp,
+			const MR_Stack_Layout_Entry *entry,
+			Word *base_sp, Word *base_curfr);
+
+/*
 ** MR_print_proc_id prints an identification of the given procedure,
 ** consisting of "pred" or "func", module name, pred or func name, arity,
-** mode number and determinism, followed by an optional extra string,
-** and a newline.
-**
-** If the procedure has trace layout information and the relevant one of
-** base_sp and base_curfr is not NULL, it also prints the call event number,
-** call sequence number and call depth of the call.
+** mode number and determinism. It does not output a newline, so that
+** the caller can pu something else after the procedure id on the same line.
 */
 
-void	MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
-			const char *extra, Word *base_sp, Word *base_curfr);
+extern	void	MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry);
+
+/*
+** MR_print_proc_id_trace_and_context prints an identification of the given
+** procedure, together with call trace information (if available), a context
+** within the procedure, and possibly a context identifying the caller.
+** The position argument says where (if anywhere) the contexts should appear.
+*/
+
+typedef	enum {
+	MR_CONTEXT_NOWHERE,
+	MR_CONTEXT_BEFORE,
+	MR_CONTEXT_AFTER,
+	MR_CONTEXT_PREVLINE,
+	MR_CONTEXT_NEXTLINE,
+} MR_Context_Position;
+
+extern	void	MR_print_proc_id_trace_and_context(FILE *fp,
+			MR_Context_Position pos,
+			const MR_Stack_Layout_Entry *entry,
+			Word *base_sp, Word *base_curfr, const char *path,
+			const char *filename, int lineno, bool print_parent,
+			const char *parent_filename, int parent_lineno,
+			int indent);
 
 /*
-** MR_dump_stack_record_print() simply wraps the call of MR_print_proc_id() with
-** the printing of an adequate number of blank lines.
+** MR_dump_stack_record_print() prints one line of a stack dump.
 */
 
-void	MR_dump_stack_record_print(FILE *fp, 
+extern	void	MR_dump_stack_record_print(FILE *fp, 
 			const MR_Stack_Layout_Entry *entry_layout, int count, 
-			int start_level, Word *base_sp, Word *base_curfr);
+			int start_level, Word *base_sp, Word *base_curfr,
+			const char *filename, int linenumber,
+			bool context_mismatch);
 
 #endif /* MERCURY_STACK_TRACE_H */
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing scripts
cvs diff: Diffing tools
cvs diff: Diffing trace
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.31
diff -u -b -r1.31 mercury_trace_external.c
--- mercury_trace_external.c	1999/11/04 18:11:16	1.31
+++ mercury_trace_external.c	1999/11/10 03:17:03
@@ -183,14 +183,18 @@
 			const char *extra, Word *base_sp, Word *base_curfr);
 static void	MR_dump_stack_record_print_to_socket(FILE *fp, 
 			const MR_Stack_Layout_Entry *entry_layout, int count, 
-			int start_level, Word *base_sp, Word *base_curfr);
+			int start_level, Word *base_sp, Word *base_curfr,
+			const char *filename, int linenumber,
+			bool context_mismatch);
 static void	MR_get_list_modules_to_import(Word debugger_request, 
-			Integer *modules_list_length_ptr, Word *modules_list_ptr);
+			Integer *modules_list_length_ptr,
+			Word *modules_list_ptr);
 static void	MR_get_mmc_options(Word debugger_request, 
 			String *mmc_options_ptr);
 static void	MR_get_object_file_name(Word debugger_request, 
 			String *object_file_name_ptr);
-static void	MR_get_variable_name(Word debugger_request, String *var_name_ptr);
+static void	MR_get_variable_name(Word debugger_request,
+			String *var_name_ptr);
 static void	MR_trace_browse_one_external(MR_Var_Spec which_var);
 static void	MR_COLLECT_filter(void (*filter_ptr)(Integer, Integer, Integer, 
 			Word, Word, String, String, String, Integer, Integer, 
@@ -476,7 +480,6 @@
 	static bool    	collect_linked = FALSE;
 	bool    	stop_collecting = FALSE;
 	Integer		debugger_request_type;
-	Integer		live_var_number;
 	Word		debugger_request;
 	Word		var_list;
 	Word		var_names_list;
@@ -635,11 +638,10 @@
 				}
 				do_init_modules();
 				message = MR_dump_stack_from_layout(
-					stdout,
-					layout->MR_sll_entry,
+					stdout, layout,
 					MR_saved_sp(saved_regs),
 					MR_saved_curfr(saved_regs),
-					include_trace_data,
+					include_trace_data, FALSE,
 					&MR_dump_stack_record_print_to_socket);
 				MR_send_message_to_socket("end_stack");
 				if (message != NULL) {
@@ -799,8 +801,6 @@
 			  }
 			case MR_REQUEST_COLLECT:
 			  {
-				static char *MERCURY_OPTIONS;
-
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_COLLECT\n");
@@ -1280,7 +1280,8 @@
 static void
 MR_dump_stack_record_print_to_socket(FILE *fp, 
 	const MR_Stack_Layout_Entry *entry_layout, int count, int start_level, 
-	Word *base_sp, Word *base_curfr)
+	Word *base_sp, Word *base_curfr, const char *filename, int linenumber,
+	bool context_mismatch)
 {
 	MR_send_message_to_socket_format("level(%d).\n", start_level);
 	MR_print_proc_id_to_socket(entry_layout, NULL, base_sp, base_curfr);
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.56
diff -u -b -r1.56 mercury_trace_internal.c
--- mercury_trace_internal.c	1999/10/18 15:47:18	1.56
+++ mercury_trace_internal.c	1999/11/10 03:20:37
@@ -92,7 +92,9 @@
 ** echos things anyway, so in that case we ignore this variable.
 */
 
+#ifdef MR_NO_USE_READLINE
 static	bool			MR_echo_commands = FALSE;
+#endif
 
 /*
 ** We print confirmation of commands (e.g. new aliases) if this is TRUE.
@@ -100,6 +102,8 @@
 
 static	bool			MR_trace_internal_interacting = FALSE;
 
+static	MR_Context_Position	MR_context_position = MR_CONTEXT_AFTER;
+
 typedef struct MR_Line_Struct {
 	char			*MR_line_contents;
 	struct MR_Line_Struct	*MR_line_next;
@@ -129,6 +133,7 @@
 static	MR_Next	MR_trace_handle_cmd(char **words, int word_count,
 			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
 			MR_Event_Details *event_details, Code **jumpaddr);
+static	bool	MR_parse_source_locn(char *word, const char **file, int *line);
 static	void	MR_print_stack_regs(Word *saved_regs);
 static	void	MR_print_heap_regs(Word *saved_regs);
 static	void	MR_print_tabling_regs(Word *saved_regs);
@@ -150,14 +155,13 @@
 static	void	MR_print_spy_point(int i);
 static	void	MR_trace_do_noop(void);
 
-static	void	MR_trace_set_level_and_report(int ancestor_level);
+static	void	MR_trace_set_level_and_report(int ancestor_level,
+			bool detailed);
 static	void	MR_trace_print_var(Word type_info, Word value);
 static	void	MR_trace_browse_var(Word type_info, Word value);
 
 static	const char *MR_trace_read_help_text(void);
 static	bool	MR_trace_is_number(const char *word, int *value);
-static	bool	MR_trace_is_number_prefix(char *word, char **suffix,
-			int *value);
 static	const char *MR_trace_parse_line(char *line,
 			char ***words, int *word_max, int *word_count);
 static	int	MR_trace_break_into_words(char *line,
@@ -179,10 +183,6 @@
 MR_trace_event_internal(MR_Trace_Cmd_Info *cmd, bool interactive,
 		MR_Event_Info *event_info)
 {
-	int			i;
-	int			c;
-	int			count;
-	bool			count_given;
 	Code			*jumpaddr;
 	char			*line;
 	MR_Next			res;
@@ -324,7 +324,6 @@
 {
 	char	*env;
 	char	*buf;
-	int	len;
 	FILE	*fp;
 
 	/* XXX This code is too Unix specific. */
@@ -347,20 +346,34 @@
 }
 
 static void
-MR_trace_set_level_and_report(int ancestor_level)
+MR_trace_set_level_and_report(int ancestor_level, bool detailed)
 {
 	const char			*problem;
 	const MR_Stack_Layout_Entry	*entry;
 	Word				*base_sp;
 	Word				*base_curfr;
+	const char			*filename;
+	int				lineno;
+	int				indent;
 
 	problem = MR_trace_set_level(ancestor_level);
 	if (problem == NULL) {
-		MR_trace_current_level_details(&entry, &base_sp, &base_curfr);
-		fprintf(MR_mdb_out, "%4d ", ancestor_level);
-		MR_print_proc_id(MR_mdb_out, entry, "", base_sp, base_curfr);
-		fprintf(MR_mdb_out, "Ancestor level set to %d.\n",
+		fprintf(MR_mdb_out, "Ancestor level set to %d:\n",
 			ancestor_level);
+		MR_trace_current_level_details(&entry, &filename, &lineno,
+			&base_sp, &base_curfr);
+		fprintf(MR_mdb_out, "%4d ", ancestor_level);
+		if (detailed) {
+			MR_print_call_trace_info(MR_mdb_out, entry,
+				base_sp, base_curfr);
+			indent = 26;
+		} else {
+			indent = 5;
+		}
+
+		MR_print_proc_id_trace_and_context(MR_mdb_out,
+			MR_context_position, entry, NULL, NULL, "",
+			filename, lineno, FALSE, "", 0, indent);
 	} else {
 		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "%s.\n", problem);
@@ -492,10 +505,12 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	Code **jumpaddr)
 {
-	const MR_Stack_Layout_Label
-		*layout = event_info->MR_event_sll;
-	Word 	*saved_regs = event_info->MR_saved_regs;
+	const MR_Stack_Layout_Label	*layout;
+	Word 				*saved_regs;
 
+	layout = event_info->MR_event_sll;
+	saved_regs = event_info->MR_saved_regs;
+
 	if (streq(words[0], "step")) {
 		int	n;
 
@@ -706,8 +721,6 @@
 		} else if (stop_depth == depth && MR_port_is_entry(port)) {
 			MR_trace_do_noop();
 		} else {
-			char	*retry_cmd;
-
 			/* Finish the call to be retried. */
 			cmd->MR_trace_cmd = MR_CMD_FINISH;
 			cmd->MR_trace_stop_depth = stop_depth;
@@ -720,30 +733,57 @@
 		}
 	} else if (streq(words[0], "level")) {
 		int	n;
-		if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
-			MR_trace_set_level_and_report(n);
+		bool	detailed;
+
+		detailed = FALSE;
+		if (! MR_trace_options_detailed(&detailed,
+				&words, &word_count, "browsing", "level"))
+		{
+			; /* the usage message has already been printed */
+		} else if (word_count == 2 &&
+				MR_trace_is_number(words[1], &n))
+		{
+			MR_trace_set_level_and_report(n, detailed);
 		} else {
 			MR_trace_usage("browsing", "level");
 		}
 	} else if (streq(words[0], "up")) {
 		int	n;
-		if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
+		bool	detailed;
+
+		detailed = FALSE;
+		if (! MR_trace_options_detailed(&detailed,
+				&words, &word_count, "browsing", "up"))
+		{
+			; /* the usage message has already been printed */
+		} else if (word_count == 2 &&
+				MR_trace_is_number(words[1], &n))
+		{
 			MR_trace_set_level_and_report(
-				MR_trace_current_level() + n);
+				MR_trace_current_level() + n, detailed);
 		} else if (word_count == 1) {
 			MR_trace_set_level_and_report(
-				MR_trace_current_level() + 1);
+				MR_trace_current_level() + 1, detailed);
 		} else {
 			MR_trace_usage("browsing", "up");
 		}
 	} else if (streq(words[0], "down")) {
 		int	n;
-		if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
+		bool	detailed;
+
+		detailed = FALSE;
+		if (! MR_trace_options_detailed(&detailed,
+				&words, &word_count, "browsing", "down"))
+		{
+			; /* the usage message has already been printed */
+		} else if (word_count == 2 &&
+				MR_trace_is_number(words[1], &n))
+		{
 			MR_trace_set_level_and_report(
-				MR_trace_current_level() - n);
+				MR_trace_current_level() - n, detailed);
 		} else if (word_count == 1) {
 			MR_trace_set_level_and_report(
-				MR_trace_current_level() - 1);
+				MR_trace_current_level() - 1, detailed);
 		} else {
 			MR_trace_usage("browsing", "down");
 		}
@@ -813,21 +853,22 @@
 			MR_trace_usage("browsing", "browse");
 		}
 	} else if (streq(words[0], "stack")) {
-		bool	include_trace_data;
+		bool	detailed;
 
-		include_trace_data = FALSE;
-		if (! MR_trace_options_detailed(&include_trace_data,
+		detailed = FALSE;
+		if (! MR_trace_options_detailed(&detailed,
 				&words, &word_count, "browsing", "stack"))
 		{
 			; /* the usage message has already been printed */
 		} else if (word_count == 1) {
 			const char	*msg;
 			do_init_modules();
-			msg = MR_dump_stack_from_layout(MR_mdb_out,
-					layout->MR_sll_entry,
+			msg = MR_dump_stack_from_layout(MR_mdb_out, layout,
 					MR_saved_sp(saved_regs),
 					MR_saved_curfr(saved_regs),
-					include_trace_data,
+					detailed,
+					MR_context_position !=
+						MR_CONTEXT_NOWHERE,
 					&MR_dump_stack_record_print);
 			if (msg != NULL) {
 				fflush(MR_mdb_out);
@@ -846,6 +887,9 @@
 		MR_Proc_Spec	spec;
 		MR_Spy_When	when;
 		MR_Spy_Action	action;
+		const char	*file;
+		int		line;
+		int		breakline;
 
 		if (word_count == 2 && streq(words[1], "info")) {
 			int	i;
@@ -877,7 +921,7 @@
 			int	slot;
 
 			MR_register_all_modules_and_procs(MR_mdb_out, TRUE);
-			slot = MR_add_spy_point(MR_SPY_SPECIFIC, action,
+			slot = MR_add_proc_spy_point(MR_SPY_SPECIFIC, action,
 					layout->MR_sll_entry, layout);
 			MR_print_spy_point(slot);
 		} else if (word_count == 2 &&
@@ -892,8 +936,8 @@
 					&unique);
 			if (spy_proc != NULL) {
 				if (unique) {
-					slot = MR_add_spy_point(when, action,
-						spy_proc, NULL);
+					slot = MR_add_proc_spy_point(when,
+						action, spy_proc, NULL);
 					MR_print_spy_point(slot);
 				} else {
 					fflush(MR_mdb_out);
@@ -910,7 +954,41 @@
 				fprintf(MR_mdb_err,
 					"There is no such procedure.\n");
 			}
+		} else if (word_count == 2 &&
+				MR_parse_source_locn(words[1], &file, &line))
+		{
+			int	slot;
+
+			slot = MR_add_line_spy_point(action, file, line);
+			if (slot >= 0) {
+				MR_print_spy_point(slot);
+			} else {
+				fflush(MR_mdb_out);
+				fprintf(MR_mdb_err,
+					"There is no event at %s:%d.\n",
+					file, line);
+			}
+		} else if (word_count == 2 &&
+				MR_trace_is_number(words[1], &breakline))
+		{
+			int	slot;
+
+			if (MR_find_context(layout, &file, &line)) {
+				slot = MR_add_line_spy_point(action, file,
+					breakline);
+				if (slot >= 0) {
+					MR_print_spy_point(slot);
 		} else {
+					fflush(MR_mdb_out);
+					fprintf(MR_mdb_err,
+						"There is no event or call "
+						"at %s:%d.\n",
+						file, line);
+				}
+			} else {
+				fatal_error("cannot find current filename");
+			}
+		} else {
 			MR_trace_usage("breakpoint", "break");
 		}
 	} else if (streq(words[0], "enable")) {
@@ -1158,6 +1236,78 @@
 		} else {
 			MR_trace_usage("parameter", "scroll");
 		}
+	} else if (streq(words[0], "context")) {
+		if (word_count == 2) {
+			if (streq(words[1], "none")) {
+				MR_context_position = MR_CONTEXT_NOWHERE;
+				if (MR_trace_internal_interacting) {
+					fprintf(MR_mdb_out, "Contexts "
+						"will not be printed.\n");
+				}
+			} else if (streq(words[1], "before")) {
+				MR_context_position = MR_CONTEXT_BEFORE;
+				if (MR_trace_internal_interacting) {
+					fprintf(MR_mdb_out, "Contexts "
+						"will be printed before, "
+						"on the same line.\n");
+				}
+			} else if (streq(words[1], "after")) {
+				MR_context_position = MR_CONTEXT_AFTER;
+				if (MR_trace_internal_interacting) {
+					fprintf(MR_mdb_out, "Contexts "
+						"will be printed after, "
+						"on the same line.\n");
+				}
+			} else if (streq(words[1], "prevline")) {
+				MR_context_position = MR_CONTEXT_PREVLINE;
+				if (MR_trace_internal_interacting) {
+					fprintf(MR_mdb_out, "Contexts "
+						"will be printed "
+						"on the previous line.\n");
+				}
+			} else if (streq(words[1], "nextline")) {
+				MR_context_position = MR_CONTEXT_NEXTLINE;
+				if (MR_trace_internal_interacting) {
+					fprintf(MR_mdb_out, "Contexts "
+						"will be printed "
+						"on the next line.\n");
+				}
+			} else {
+				MR_trace_usage("parameter", "context");
+			}
+		} else if (word_count == 1) {
+			fprintf(MR_mdb_out, "Contexts are ");
+			switch (MR_context_position) {
+			case MR_CONTEXT_NOWHERE:
+				fprintf(MR_mdb_out, "not printed.");
+				break;
+
+			case MR_CONTEXT_BEFORE:
+				fprintf(MR_mdb_out,
+					"printed before, on the same line.");
+				break;
+
+			case MR_CONTEXT_AFTER:
+				fprintf(MR_mdb_out,
+					"printed after, on the same line.");
+				break;
+
+			case MR_CONTEXT_PREVLINE:
+				fprintf(MR_mdb_out,
+					"printed on the previous line.");
+				break;
+
+			case MR_CONTEXT_NEXTLINE:
+				fprintf(MR_mdb_out,
+					"printed on the next line.");
+				break;
+
+			default:
+				fatal_error("invalid MR_context_position");
+			}
+		} else {
+			MR_trace_usage("parameter", "context");
+		}
 	} else if (streq(words[0], "echo")) {
 		if (word_count == 2) {
 			if (streq(words[1], "off")) {
@@ -1470,6 +1620,28 @@
 	return KEEP_INTERACTING;
 }
 
+static bool
+MR_parse_source_locn(char *word, const char **file, int *line)
+{
+	char		*s;
+	const char	*t;
+
+	if ((s = strchr(word, ':')) != NULL) {
+		for (t = s+1; *t != '\0'; t++) {
+			if (! MR_isdigit(*t)) {
+				return FALSE;
+			}
+		}
+
+		*s = '\0';
+		*file = word;
+		*line = atoi(s+1);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 static void
 MR_print_stack_regs(Word *saved_regs)
 {
@@ -1751,8 +1923,14 @@
 			(point->spy_enabled ? "+" : "-") :
 			(point->spy_enabled ? "E" : "D"),
 		MR_spy_action_string(point->spy_action),
-		MR_spy_when_string(point->spy_when));
-	MR_print_proc_id(MR_mdb_out, point->spy_proc, NULL, NULL, NULL);
+		MR_spy_when_names[point->spy_when]);
+	if (point->spy_when == MR_SPY_LINENO) {
+		fprintf(MR_mdb_out, "%s:%d\n",
+			point->spy_filename, point->spy_linenumber);
+	} else {
+		MR_print_proc_id(MR_mdb_out, point->spy_proc);
+		fprintf(MR_mdb_out, "\n");
+	}
 }
 
 /*
@@ -1924,7 +2102,6 @@
 	char	**words;
 	int	token_number;
 	int	char_pos;
-	int	int_val;
 
 	token_number = 0;
 	char_pos = 0;
@@ -2185,14 +2362,43 @@
 void
 MR_trace_event_print_internal_report(MR_Event_Info *event_info)
 {
-	fprintf(MR_mdb_out, "%8ld: %6ld %2ld %s ",
+	const MR_Stack_Layout_Label	*parent;
+	const char			*filename, *parent_filename;
+	int				lineno, parent_lineno;
+	const char			*problem; /* not used */
+	Word				*base_sp, *base_curfr;
+	int				indent;
+
+	lineno = 0;
+	parent_lineno = 0;
+	filename = "";
+	parent_filename = "";
+
+	fprintf(MR_mdb_out, "%8ld: %6ld %2ld %s",
 		(long) event_info->MR_event_number,
 		(long) event_info->MR_call_seqno,
 		(long) event_info->MR_call_depth,
 		MR_port_names[event_info->MR_trace_port]);
+	/* the printf printed 24 characters */
+	indent = 24;
+
+	(void) MR_find_context(event_info->MR_event_sll, &filename, &lineno);
+	if (MR_port_is_interface(event_info->MR_trace_port)) {
+		base_sp = MR_saved_sp(event_info->MR_saved_regs);
+		base_curfr = MR_saved_curfr(event_info->MR_saved_regs);
+		parent = MR_find_nth_ancestor(event_info->MR_event_sll, 1,
+			&base_sp, &base_curfr, &problem);
+		if (parent != NULL) {
+			(void) MR_find_context(parent, &parent_filename,
+				&parent_lineno);
+		}
+	}
 
-	MR_print_proc_id(MR_mdb_out, event_info->MR_event_sll->MR_sll_entry,
-			event_info->MR_event_path, NULL, NULL);
+	MR_print_proc_id_trace_and_context(MR_mdb_out, MR_context_position,
+		event_info->MR_event_sll->MR_sll_entry, NULL, NULL,
+		event_info->MR_event_path, filename, lineno,
+		MR_port_is_interface(event_info->MR_trace_port),
+		parent_filename, parent_lineno, indent);
 }
 
 typedef struct
@@ -2241,6 +2447,7 @@
 	{ "parameter", "printlevel" },
 	{ "parameter", "echo" },
 	{ "parameter", "scroll" },
+	{ "parameter", "context" },
 	{ "parameter", "alias" },
 	{ "parameter", "unalias" },
 	{ "help", "document_category" },
@@ -2278,4 +2485,3 @@
 
 	return FALSE;
 }
-
Index: trace/mercury_trace_spy.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_spy.c,v
retrieving revision 1.5
diff -u -b -r1.5 mercury_trace_spy.c
--- mercury_trace_spy.c	1999/10/18 15:47:25	1.5
+++ mercury_trace_spy.c	1999/11/10 03:17:03
@@ -15,8 +15,19 @@
 #include "mercury_trace_base.h"
 #include "mercury_trace.h"
 #include "mercury_trace_spy.h"
+#include "mercury_trace_tables.h"
 #include "mercury_array_macros.h"
+#include <stdlib.h>
 
+const char		*MR_spy_when_names[] =
+{
+	"all",
+	"interface",
+	"entry",
+	"specific",
+	"linenumber",
+};
+
 /*
 ** The table of spy points, with one entry per existing (or deleted but
 ** not yet reused) spy point, with counters saying which is the next
@@ -50,11 +61,35 @@
 /* The initial size of the spied procs table. */
 #define	MR_INIT_SPIED_PROCS	10
 
+/*
+** The table of spied on return labels, with one entry per return label
+** that is currently being spied on, ordered on label layout structure address,
+** and with counters saying which is the next free slot and how many slots
+** are allocated.
+*/
+
+typedef struct {
+	const MR_Stack_Layout_Label	*spy_label;
+	int				spy_point_num;
+} MR_Spied_Label;
+
+static	MR_Spied_Label	*MR_spied_labels;
+static	int		MR_spied_label_next = 0;
+static	int		MR_spied_label_max = 0;
+
+/* The initial size of the spied labels table. */
+#define	MR_INIT_SPIED_LABELS	10
+
 /**************************************************************************/
 
 static	int	MR_compare_addr(const void *address1, const void *address2);
 static	int	MR_search_spy_table_for_proc(const MR_Stack_Layout_Entry
 			*entry);
+static	int	MR_search_spy_table_for_label(const MR_Stack_Layout_Label
+			*label);
+static	void	MR_add_line_spy_point_callback(const MR_Stack_Layout_Label
+			*label, int spy_point_num);
+static	int	MR_compare_spied_labels(const void *, const void *);
 
 /*
 ** Compare two addresses, and return an integer which is <0, 0, or >0
@@ -101,6 +136,26 @@
 	}
 }
 
+/*
+** Return the index of the entry in MR_spied_labels whose spy_label field
+** is label, or a negative number if absent.
+*/
+
+static int
+MR_search_spy_table_for_label(const MR_Stack_Layout_Label *label)
+{
+	int	slot;
+	bool	found;
+
+	MR_bsearch(MR_spied_label_next, slot, found,
+		MR_compare_addr(MR_spied_labels[slot].spy_label, label));
+	if (found) {
+		return slot;
+	} else {
+		return -1;
+	}
+}
+
 bool
 MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout,
 	MR_Trace_Port port, MR_Spy_Action *action_ptr)
@@ -109,14 +164,60 @@
 	bool				enabled;
 	MR_Spy_Point			*point;
 	MR_Spy_Action			action;
+	const MR_Stack_Layout_Label	*parent;
+	const char			*problem;
+	Word				*base_sp;
+	Word				*base_curfr;
 
-	slot = MR_search_spy_table_for_proc(layout->MR_sll_entry);
-	if (slot < 0) {
-		return FALSE;
-	}
-
 	enabled = FALSE;
 	action = MR_SPY_PRINT;
+
+	if (MR_spied_label_next > 0) {
+		slot = MR_search_spy_table_for_label(layout);
+		if (slot >= 0) {
+			point = MR_spy_points[
+				MR_spied_labels[slot].spy_point_num];
+			if (point->spy_enabled) {
+				if (point->spy_when != MR_SPY_LINENO) {
+					fatal_error("non-lineno spy "
+						"point in "
+						"spied labels array");
+				}
+
+				enabled = TRUE;
+				action = max(action,
+					point->spy_action);
+			}
+		}
+
+		if (MR_port_is_interface(port)) {
+			restore_transient_registers();
+			base_sp = MR_sp;
+			base_curfr = MR_curfr;
+			parent = MR_find_nth_ancestor(layout, 1,
+				&base_sp, &base_curfr, &problem);
+			if (parent != NULL && 0 <=
+				(slot = MR_search_spy_table_for_label(parent)))
+			{
+				point = MR_spy_points[MR_spied_labels[slot].
+					spy_point_num];
+				if (point->spy_enabled) {
+					if (point->spy_when != MR_SPY_LINENO) {
+						fatal_error("non-lineno spy "
+							"point in "
+							"spied labels array");
+					}
+
+					enabled = TRUE;
+					action = max(action,
+						point->spy_action);
+				}
+			}
+		}
+	}
+
+	slot = MR_search_spy_table_for_proc(layout->MR_sll_entry);
+	if (slot >= 0) {
 	for (point = MR_spied_procs[slot].spy_points; point != NULL;
 			point = point->spy_next) {
 		if (! point->spy_enabled) {
@@ -127,13 +228,15 @@
 
 			case MR_SPY_ALL:
 				enabled = TRUE;
-				action = max(action, point->spy_action);
+					action = max(action,
+						point->spy_action);
 				break;
 
 			case MR_SPY_ENTRY:
 				if (MR_port_is_entry(port)) {
 					enabled = TRUE;
-					action = max(action, point->spy_action);
+						action = max(action,
+							point->spy_action);
 				} else {
 					continue;
 				}
@@ -143,7 +246,8 @@
 			case MR_SPY_INTERFACE:
 				if (MR_port_is_interface(port)) {
 					enabled = TRUE;
-					action = max(action, point->spy_action);
+						action = max(action,
+							point->spy_action);
 				} else {
 					continue;
 				}
@@ -153,18 +257,24 @@
 			case MR_SPY_SPECIFIC:
 				if (layout == point->spy_label) {
 					enabled = TRUE;
-					action = max(action, point->spy_action);
+						action = max(action,
+							point->spy_action);
 				} else {
 					continue;
 				}
 
 				break;
 
+				case MR_SPY_LINENO:
+					fatal_error("lineno spy point in "
+						"spied procs array");
+
 			default:
 				fatal_error("bad spy point when in "
 						"MR_event_matches_spy_point");
 		}
 	}
+	}
 
 	if (enabled) {
 		*action_ptr = action;
@@ -175,14 +285,13 @@
 }
 
 int
-MR_add_spy_point(MR_Spy_When when, MR_Spy_Action action,
+MR_add_proc_spy_point(MR_Spy_When when, MR_Spy_Action action,
 	const MR_Stack_Layout_Entry *entry, const MR_Stack_Layout_Label *label)
 {
 	MR_Spy_Point	*point;
 	int		point_slot;
 	int		proc_slot;
 	int		i;
-	bool		found;
 
 	proc_slot = MR_search_spy_table_for_proc(entry);
 	if (proc_slot < 0) {
@@ -223,6 +332,76 @@
 	return point_slot;
 }
 
+int
+MR_add_line_spy_point(MR_Spy_Action action,
+	const char *filename, int linenumber)
+{
+	MR_Spy_Point	*point;
+	int		point_slot;
+	int		old_size, new_size;
+
+	point_slot = MR_spy_point_next;
+
+	old_size = MR_spied_label_next;
+	MR_process_file_line_layouts(filename, linenumber,
+		MR_add_line_spy_point_callback, point_slot);
+	new_size = MR_spied_label_next;
+
+	if (new_size == old_size) {
+		/* there were no matching labels */
+		return -1;
+	}
+
+	/*
+	** The matching labels were added at the end of the spied label table.
+	** We must make the table sorted again.
+	*/
+
+	qsort(MR_spied_labels, MR_spied_label_next, sizeof(MR_Spied_Label), 
+		MR_compare_spied_labels);
+
+	point = MR_NEW(MR_Spy_Point);
+	point->spy_when       = MR_SPY_LINENO;
+	point->spy_exists     = TRUE;
+	point->spy_enabled    = TRUE;
+	point->spy_action     = action;
+	point->spy_filename   = filename;
+	point->spy_linenumber = linenumber;
+
+	MR_ensure_room_for_next(MR_spy_point, MR_Spy_Point *,
+		MR_INIT_SPY_POINTS);
+	MR_spy_points[point_slot] = point;
+	MR_spy_point_next++;
+
+	return point_slot;
+}
+
+static void
+MR_add_line_spy_point_callback(const MR_Stack_Layout_Label *label,
+	int spy_point_num)
+{
+	int	spied_label_slot;
+
+	MR_ensure_room_for_next(MR_spied_label, MR_Spied_Label,
+		MR_INIT_SPIED_LABELS);
+	spied_label_slot = MR_spied_label_next;
+	MR_spied_labels[spied_label_slot].spy_label = label;
+	MR_spied_labels[spied_label_slot].spy_point_num = spy_point_num;
+	MR_spied_label_next++;
+}
+
+static int
+MR_compare_spied_labels(const void *l1, const void *l2)
+{
+	const MR_Spied_Label	*label1, *label2;
+
+	label1 = (const MR_Spied_Label *) l1;
+	label2 = (const MR_Spied_Label *) l2;
+
+	return (int) ((Integer) label1->spy_label
+		- (Integer) label2->spy_label);
+}
+
 void
 MR_delete_spy_point(int point_table_slot)
 {
@@ -230,16 +409,43 @@
 	MR_Spy_Point	**cur_addr;
 	MR_Spy_Point	*cur;
 	int		proc_table_slot;
+	int		i;
+	int		label_slot;
 
 	point = MR_spy_points[point_table_slot];
 
-	/* this effectively remove the point from the spypoint table */
+	/* this effectively removes the point from the spypoint table */
 	point->spy_exists = FALSE;
+
+	if (point->spy_when == MR_SPY_LINENO) {
+		/*
+		** Remove the spy point from the spied label table list.
+		*/
+
+		label_slot = 0;
+		for (i = 0; i < MR_spied_label_next; i++) {
+			if (MR_spied_labels[i].spy_point_num !=
+				point_table_slot)
+			{
+				MR_spied_labels[label_slot].spy_label =
+					MR_spied_labels[i].spy_label;
+				MR_spied_labels[label_slot].spy_point_num =
+					MR_spied_labels[i].spy_point_num;
+				label_slot++;
+			}
+		}
+
+		MR_spied_label_next = label_slot;
+	} else {
+		/*
+		** Remove the spy point from the spied proc table list
+		** for its proc.
+		*/
 
-	/* now remove the point from the spied proc table list for its proc */
 	proc_table_slot = MR_search_spy_table_for_proc(point->spy_proc);
 	if (proc_table_slot < 0) {
-		fatal_error("deleted spy point was not indexed by proc addr");
+			fatal_error("deleted spy point "
+				"was not indexed by proc addr");
 	}
 
 	cur_addr = &MR_spied_procs[proc_table_slot].spy_points;
@@ -250,8 +456,10 @@
 	}
 
 	if (cur == NULL) {
-		fatal_error("deleted spy point was not on proc index list");
+			fatal_error("deleted spy point "
+				"was not on proc index list");
 	}
 
 	*cur_addr = point->spy_next;
+	}
 }
Index: trace/mercury_trace_spy.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_spy.h,v
retrieving revision 1.2
diff -u -b -r1.2 mercury_trace_spy.h
--- mercury_trace_spy.h	1999/10/07 09:31:41	1.2
+++ mercury_trace_spy.h	1999/10/28 06:51:41
@@ -23,14 +23,14 @@
 					"unknown spy action")
 
 typedef enum {
-	MR_SPY_ALL, MR_SPY_INTERFACE, MR_SPY_ENTRY, MR_SPY_SPECIFIC
+	MR_SPY_ALL,
+	MR_SPY_INTERFACE,
+	MR_SPY_ENTRY,
+	MR_SPY_SPECIFIC,
+	MR_SPY_LINENO
 } MR_Spy_When;
 
-#define	MR_spy_when_string(w)		((w == MR_SPY_ALL) ? "all" :          \
-					(w == MR_SPY_INTERFACE) ? "interface":\
-					(w == MR_SPY_ENTRY) ? "entry" : \
-					(w == MR_SPY_SPECIFIC) ? "specific" : \
-					"unknown spy when")
+extern	const char	*MR_spy_when_names[];
 
 typedef struct MR_Spy_Point_Struct MR_Spy_Point;
 
@@ -39,9 +39,11 @@
 	bool				spy_enabled;
 	MR_Spy_When			spy_when;
 	MR_Spy_Action			spy_action;
-	const MR_Stack_Layout_Entry	*spy_proc;
-	const MR_Stack_Layout_Label	*spy_label; /* if MR_SPY_SPECIFIC */
-	MR_Spy_Point			*spy_next;
+	const MR_Stack_Layout_Entry	*spy_proc;      /* if not LINENO */
+	const MR_Stack_Layout_Label	*spy_label;	/* if SPECIFIC */
+	const char			*spy_filename;  /* if LINENO */
+	int				spy_linenumber; /* if LINENO */
+	MR_Spy_Point			*spy_next;	/* if not LINENO */
 };
 
 /*
@@ -64,13 +66,22 @@
 				MR_Spy_Action *action);
 
 /*
-** Add a new spy point to the table.
+** Add a new spy point on a procedure (as opposed to on a line number)
+** to the table.
 */
 
-extern	int		MR_add_spy_point(MR_Spy_When when,
+extern	int		MR_add_proc_spy_point(MR_Spy_When when,
 				MR_Spy_Action action,
 				const MR_Stack_Layout_Entry *entry,
 				const MR_Stack_Layout_Label *label);
+
+/*
+** Add a new spy point on a line number (as opposed to on a procedure)
+** to the table.
+*/
+
+extern	int		MR_add_line_spy_point(MR_Spy_Action action,
+				const char *filename, int linenumber);
 
 /*
 ** Delete a spy point from the table.
Index: trace/mercury_trace_tables.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_tables.c,v
retrieving revision 1.8
diff -u -b -r1.8 mercury_trace_tables.c
--- mercury_trace_tables.c	1999/10/18 15:47:26	1.8
+++ mercury_trace_tables.c	1999/11/10 03:17:03
@@ -33,6 +33,9 @@
 			const MR_Module_Layout *module, MR_Proc_Spec *spec,
 			void f(void *, const MR_Stack_Layout_Entry *),
 			void *);
+static	void	MR_process_line_layouts(MR_Module_File_Layout *file_layout,
+			int line, MR_file_line_callback callback_func,
+			int callback_arg);
 
 void
 MR_register_all_modules_and_procs(FILE *fp, bool verbose)
@@ -111,6 +114,58 @@
 }
 
 void
+MR_process_file_line_layouts(const char *file, int line,
+	MR_file_line_callback callback_func, int callback_arg)
+{
+	int			i, j;
+	MR_Module_File_Layout	*file_layout;
+
+	for (i = 0; i < MR_module_info_next; i++) {
+		for (j = 0; j < MR_module_infos[i]->MR_ml_filename_count; j++)
+		{
+			file_layout = MR_module_infos[i]->
+					MR_ml_module_file_layout[j];
+			if (streq(file_layout->MR_mfl_filename, file)) {
+				MR_process_line_layouts(file_layout, line,
+					callback_func, callback_arg);
+			}
+		}
+	}
+}
+
+static void
+MR_process_line_layouts(MR_Module_File_Layout *file_layout, int line,
+	MR_file_line_callback callback_func, int callback_arg)
+{
+	int			k;
+	bool			found;
+
+	MR_bsearch(file_layout->MR_mfl_label_count, k, found,
+		file_layout->MR_mfl_label_lineno[k] - line);
+
+	if (found) {
+		/*
+		** The binary search found *one* label with the given
+		** linenumber; we now find the *first* such label.
+		*/
+
+		while (k > 0
+			&& file_layout->MR_mfl_label_lineno[k - 1] == line)
+		{
+			k--;
+		}
+
+		while (k < file_layout->MR_mfl_label_count
+			&& file_layout->MR_mfl_label_lineno[k] == line)
+		{
+			(*callback_func)(file_layout->MR_mfl_label_layout[k],
+				callback_arg);
+			k++;
+		}
+	}
+}
+
+void
 MR_dump_module_tables(FILE *fp)
 {
 	int	i, j;
@@ -223,7 +278,17 @@
 		*slash = '\0';
 	}
 
+	if (MR_isdigit(*str)) {
+		/* this looks to be a line number */
+		return FALSE;
+	}
+
 	for (s = str; *s != '\0'; s++) {
+		if (*s == ':' && MR_isdigit(*(s+1))) {
+			/* this looks to be filename:linenumber */
+			return FALSE;
+		}
+
 		if (*s == ':' || (*s == '_' && *(s+1) == '_')) {
 			if (*s == ':') {
 				spec->MR_proc_name = s+1;
@@ -336,6 +401,7 @@
 MR_print_proc_id_for_debugger(FILE *fp,
 	const MR_Stack_Layout_Entry *entry_layout)
 {
-	MR_print_proc_id(fp, entry_layout, NULL, NULL, NULL);
+	MR_print_proc_id(fp, entry_layout);
+	fprintf(fp, "\n");
 }
 
Index: trace/mercury_trace_tables.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_tables.h,v
retrieving revision 1.5
diff -u -b -r1.5 mercury_trace_tables.h
--- mercury_trace_tables.h	1999/05/28 05:29:41	1.5
+++ mercury_trace_tables.h	1999/10/29 01:25:46
@@ -37,6 +37,21 @@
 				*module);
 
 /*
+** MR_process_file_line_layouts searches all the module layout structures
+** of the program for label layout structures corresponding to the given
+** filename/linenumber combination. For all such labels, it calls the supplied
+** callback function with a pointer to the label's layout structure and
+** with the supplied integer callback argument.
+*/
+
+typedef	void		(*MR_file_line_callback)(const MR_Stack_Layout_Label *,
+				int);
+
+extern	void		MR_process_file_line_layouts(const char *file,
+				int line, MR_file_line_callback callback_func,
+				int callback_arg);
+
+/*
 ** These functions print (parts of) the module info table.
 **
 ** MR_dump_module_tables lists all procedures in all modules.
Index: trace/mercury_trace_vars.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_vars.c,v
retrieving revision 1.9
diff -u -b -r1.9 mercury_trace_vars.c
--- mercury_trace_vars.c	1999/07/23 04:23:09	1.9
+++ mercury_trace_vars.c	1999/11/10 03:38:45
@@ -95,6 +95,8 @@
 	const char			*MR_point_problem;
 	int				MR_point_level;
 	const MR_Stack_Layout_Entry	*MR_point_level_entry;
+	const char			*MR_point_level_filename;
+	int				MR_point_level_linenumber;
 	Word				*MR_point_level_base_sp;
 	Word				*MR_point_level_base_curfr;
 	int				MR_point_var_count;
@@ -227,6 +229,8 @@
 	const char			*name;
 	const char			*string_table;
 	Integer				string_table_size;
+	const char			*filename;
+	int				linenumber;
 
 	problem = NULL;
 	top_layout = MR_point.MR_point_top_layout;
@@ -255,6 +259,11 @@
 		return "there is no information about live variables";
 	}
 
+	if (! MR_find_context(level_layout, &filename, &linenumber)) {
+		filename = "";
+		linenumber = 0;
+	}
+
 	/*
 	** After this point, we cannot find any more problems
 	** that would prevent us from assembling an accurate picture
@@ -265,6 +274,8 @@
 	MR_point.MR_point_problem = NULL;
 	MR_point.MR_point_level = ancestor_level;
 	MR_point.MR_point_level_entry = entry;
+	MR_point.MR_point_level_filename = filename;
+	MR_point.MR_point_level_linenumber = linenumber;
 	MR_point.MR_point_level_base_sp = base_sp;
 	MR_point.MR_point_level_base_curfr = base_curfr;
 
@@ -484,6 +495,7 @@
 
 void
 MR_trace_current_level_details(const MR_Stack_Layout_Entry **entry_ptr,
+	const char **filename_ptr, int *linenumber_ptr,
 	Word **base_sp_ptr, Word **base_curfr_ptr)
 {
 	if (MR_point.MR_point_problem != NULL) {
@@ -492,6 +504,14 @@
 
 	if (entry_ptr != NULL) {
 		*entry_ptr = MR_point.MR_point_level_entry;
+	}
+
+	if (filename_ptr != NULL) {
+		*filename_ptr = MR_point.MR_point_level_filename;
+	}
+
+	if (linenumber_ptr != NULL) {
+		*linenumber_ptr = MR_point.MR_point_level_linenumber;
 	}
 
 	if (base_sp_ptr != NULL) {
Index: trace/mercury_trace_vars.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_vars.h,v
retrieving revision 1.2
diff -u -b -r1.2 mercury_trace_vars.h
--- mercury_trace_vars.h	1999/05/28 07:13:38	1.2
+++ mercury_trace_vars.h	1999/11/04 06:39:12
@@ -58,6 +58,7 @@
 extern	int		MR_trace_current_level(void);
 extern	void		MR_trace_current_level_details(
 				const MR_Stack_Layout_Entry **entry_ptr,
+				const char **filename_ptr, int *linenumber_ptr,
 				Word **base_sp_ptr, Word **base_curfr_ptr);
 
 /*
cvs diff: Diffing trial
cvs diff: Diffing util
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list