for review: big step towards a usable debugger, round 3 (part 3 of 3)

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Apr 8 18:49:52 AEST 1998


diff -u ws4/compiler/trace.m ws2/compiler/trace.m
--- ws4/compiler/trace.m	Tue Apr  7 16:38:29 1998
+++ ws2/compiler/trace.m	Tue Mar 31 20:50:00 1998
@@ -3,7 +3,9 @@
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-
+%
+% Author: zs.
+%
 % This module handles the generation of traces for the trace analysis system.
 %
 % For the general basis of trace analysis systems, see the paper
@@ -11,13 +13,31 @@
 % available from http://www.irisa.fr/lande/ducasse.
 %
 % We reserve two slots in the stack frame of the traced procedure.
-% One contains the call sequence number, which is set in the procedure prolog
+% One contains the call sequence number, which is set in the procedure prologue
 % by incrementing a global counter. The other contains the call depth, which
 % is also set by incrementing a global variable containing the depth of the
 % caller. The caller sets this global variable from its own saved depth
 % just before the call.
-
-% Author: zs.
+%
+% Each event has a label associated with it. The stack layout for that label
+% records what variables are live and where they are at the time of the event.
+% These labels are generated by the same predicate that generates the code
+% for the event, and are initially not used for anything else.
+% However, some of these labels may be fallen into from other places,
+% and thus optimization may redirect references from labels to one of these
+% labels. This cannot happen in the opposite direction, due to the reference
+% to each event's label from the event's pragma C code instruction.
+% (This prevents labelopt from removing the label.)
+%
+% We classify events into three kinds: external events (call, exit, fail),
+% internal events (switch, disj, ite_then, ite_else), and nondet pragma C
+% events (first, later). Code_gen.m, which calls this module to generate
+% all external events, checks whether tracing is required before calling us;
+% the predicates handing internal and nondet pragma C events must check this
+% themselves. The predicates generating internal events need the goal
+% following the event as a parameter. For the first and later arms of
+% nondet pragma C code, there is no such hlds_goal, which is why these events
+% need a bit of special treatment.
 
 %-----------------------------------------------------------------------------%
 
@@ -25,24 +45,28 @@
 
 :- interface.
 
-:- import_module prog_data, hlds_goal, hlds_pred, llds, code_info.
-:- import_module list, assoc_list, set, term.
-
-:- type trace_port	--->	call
-			;	exit
-			;	fail
-			;	ite_then(goal_path, set(var))
-			;	ite_else(goal_path, set(var))
-			;	switch(goal_path, set(var))
-			;	disj(goal_path, set(var)).
+:- import_module hlds_goal, hlds_pred, hlds_module.
+:- import_module prog_data, llds, code_info.
+:- import_module assoc_list, set, term.
+
+:- type external_trace_port
+	--->	call
+	;	exit
+	;	fail.
+
+:- type nondet_pragma_trace_port
+	--->	nondet_pragma_first
+	;	nondet_pragma_later.
 
 :- type trace_info.
 
 	% Return the set of input variables whose values should be preserved
-	% until the exit and fail ports. This should be all input variables,
-	% except those that may be clobbered during the evaluation of the
-	% procedure.
-:- pred trace__fail_vars(proc_info::in, set(var)::out) is det.
+	% until the exit and fail ports. This will be all the input variables,
+	% except those that can be totally clobbered during the evaluation
+	% of the procedure (those partially clobbered may still be of interest,
+	% although to handle them properly we need to record insts in stack
+	% layouts).
+:- pred trace__fail_vars(module_info::in, proc_info::in, set(var)::out) is det.
 
 	% Set up the code generator state for tracing, by reserving
 	% slots for the call number and call depth.
@@ -54,13 +78,24 @@
 	% Generate code to reset the call depth before a call.
 :- pred trace__generate_depth_reset_code(trace_info::in, code_tree::out) is det.
 
-	% Generate code for a trace event.
-:- pred trace__generate_event_code(trace_port::in, trace_info::in,
+	% If generate_trace is set, generate code for an internal trace event.
+	% This predicate must be called just before generating code for the
+	% given goal.
+:- pred trace__maybe_generate_internal_event_code(hlds_goal::in,
+	code_tree::out, code_info::in, code_info::out) is det.
+
+	% If generate_trace is set, 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.
 
-	% Generate code for a trace event, returning the
-:- pred trace__generate_event_code(trace_port::in, trace_info::in,
-	label::out, assoc_list(tvar, lval)::out, code_tree::out,
+	% Generate code for an external trace event.
+	% Besides the trace code, we return the label on which we have hung
+	% the trace liveness information and data on the type variables in the
+	% 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, assoc_list(tvar, lval)::out, code_tree::out,
 	code_info::in, code_info::out) is det.
 
 :- pred trace__path_to_string(goal_path::in, string::out) is det.
@@ -69,27 +104,52 @@
 
 :- implementation.
 
-:- import_module hlds_module, llds_out, code_util, type_util.
-:- import_module arg_info, continuation_info, instmap, tree.
-:- import_module bool, int, string, map, std_util, varset, require.
+:- import_module continuation_info, type_util, llds_out, tree.
+:- import_module (inst), instmap, inst_match, mode_util.
+:- import_module list, bool, int, string, map, std_util, varset, require.
+
+:- type trace_port
+	--->	call
+	;	exit
+	;	fail
+	;	ite_then
+	;	ite_else
+	;	switch
+	;	disj
+	;	nondet_pragma_first
+	;	nondet_pragma_later.
+
+	% Information specific to a trace port.
+:- type trace_port_info
+	--->	external
+	;	internal(
+			goal_path,	% The path of the goal whose start
+					% this port represents.
+			set(var)	% The pre-death set of this goal.
+		)
+	;	nondet_pragma.
 
+	% Information for tracing that is valid throughout the execution
+	% of a procedure.
 :- type trace_info
 	--->	trace_info(
 			lval,	% stack slot of call sequence number
 			lval	% stack slot of call depth
 		).
 
-trace__fail_vars(ProcInfo, FailVars) :-
+trace__fail_vars(ModuleInfo, ProcInfo, FailVars) :-
 	proc_info_headvars(ProcInfo, HeadVars),
+	proc_info_argmodes(ProcInfo, Modes),
 	proc_info_arg_info(ProcInfo, ArgInfos),
-	assoc_list__from_corresponding_lists(HeadVars, ArgInfos, Args),
-	arg_info__build_input_arg_list(Args, ArgList),
-	assoc_list__keys(ArgList, InputArgs),
-		% We do not yet delete input vars that have any components
-		% that could be clobbered, because the modules of the mode
-		% system do not have any utility predicates for testing for
-		% this.
-	set__list_to_set(InputArgs, FailVars).
+	mode_list_get_final_insts(Modes, ModuleInfo, Insts),
+	(
+		trace__build_fail_vars(HeadVars, Insts, ArgInfos,
+			ModuleInfo, FailVarsList)
+	->
+		set__list_to_set(FailVarsList, FailVars)
+	;
+		error("length mismatch in trace__fail_vars")
+	).
 
 trace__setup -->
 	code_info__get_trace_slot(CallNumSlot),
@@ -119,13 +179,76 @@
 		c_code(Stmt) - ""
 	]).
 
-trace__generate_event_code(Port, TraceInfo, Code) -->
-	trace__generate_event_code(Port, TraceInfo, _, _, Code).
+trace__maybe_generate_internal_event_code(Goal, Code) -->
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ Goal = _ - GoalInfo },
+		{ goal_info_get_goal_path(GoalInfo, Path) },
+		{ goal_info_get_pre_deaths(GoalInfo, PreDeaths) },
+		{
+			Path = [LastStep | _],
+			(
+				LastStep = switch(_),
+				PortPrime = switch
+			;
+				LastStep = disj(_),
+				PortPrime = disj
+			;
+				LastStep = ite_then,
+				PortPrime = ite_then
+			;
+				LastStep = ite_else,
+				PortPrime = ite_else
+			)
+		->
+			Port = PortPrime
+		;
+			error("trace__generate_internal_event_code: bad path")
+		},
+		trace__generate_event_code(Port, internal(Path, PreDeaths),
+			TraceInfo, _, _, Code)
+	;
+		{ Code = empty }
+	).
+
+trace__maybe_generate_pragma_event_code(PragmaPort, Code) -->
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ trace__convert_nondet_pragma_port_type(PragmaPort, Port) },
+		trace__generate_event_code(Port, nondet_pragma, TraceInfo,
+			_, _, Code)
+	;
+		{ Code = empty }
+	).
+
+trace__generate_external_event_code(ExternalPort, TraceInfo,
+		Label, TvarDataList, Code) -->
+	{ trace__convert_external_port_type(ExternalPort, Port) },
+	trace__generate_event_code(Port, external, TraceInfo,
+		Label, TvarDataList, Code).
+
+:- pred trace__generate_event_code(trace_port::in, trace_port_info::in,
+	trace_info::in, label::out, assoc_list(tvar, lval)::out,
+	code_tree::out, code_info::in, code_info::out) is det.
 
-trace__generate_event_code(Port, TraceInfo, Label, TvarDataList, Code) -->
+trace__generate_event_code(Port, PortInfo, TraceInfo, Label, TvarDataList,
+		Code) -->
 	code_info__get_next_label(Label),
 	code_info__get_known_variables(LiveVars0),
-	{ trace__apply_pre_deaths(Port, LiveVars0, LiveVars) },
+	{
+		PortInfo = external,
+		LiveVars = LiveVars0,
+		PathStr = ""
+	;
+		PortInfo = internal(Path, PreDeaths),
+		set__to_sorted_list(PreDeaths, PreDeathList),
+		list__delete_elems(LiveVars0, PreDeathList, LiveVars),
+		trace__path_to_string(Path, PathStr)
+	;
+		PortInfo = nondet_pragma,
+		LiveVars = [],
+		PathStr = ""
+	},
 	code_info__get_varset(VarSet),
 	code_info__get_instmap(InstMap),
 	{ set__init(TvarSet0) },
@@ -149,13 +272,8 @@
 	Quote = """",
 	Comma = ", ",
 	trace__port_to_string(Port, PortStr),
-	( trace__port_path(Port, Path) ->
-		trace__path_to_string(Path, PathStr)
-	;
-		PathStr = ""
-	),
 	IfStmt = "\tif (MR_trace_enabled) {\n",
-	EndStmt = "\t}\n",
+	EndStmt = "\t}",
 	SaveStmt = "\t\tsave_transient_registers();\n",
 	RestoreStmt = "\t\trestore_transient_registers();\n",
 	string__int_to_string(MaxReg, MaxRegStr),
@@ -164,22 +282,26 @@
 		"\t\t\t&mercury_data__stack_layout__", LabelStr, Comma, "\n",
 		"\t\t\t", PortStr, Comma,
 		CallNumStr, Comma,
-		CallDepthStr, Comma,
-		Quote, PathStr, Quote, Comma,
+		CallDepthStr, Comma, "\n",
+		"\t\t\t", Quote, PathStr, Quote, Comma,
 		MaxRegStr, ");\n"],
 		CallStmt),
 	string__append_list([IfStmt, SaveStmt, CallStmt, RestoreStmt, EndStmt],
 		TraceStmt),
 	TraceCode =
 		node([
-			pragma_c([], [pragma_c_raw_code(TraceStmt)],
-				may_call_mercury, yes(Label))
-				- "",
 			label(Label)
-				- "A label to hang trace liveness on"
+				- "A label to hang trace liveness on",
 				% Referring to the label from the pragma_c
 				% prevents the label from being renamed
 				% or optimized away.
+				% The label is before the trace code
+				% because sometimes this pair is preceded
+				% by another label, and this way we can
+				% eliminate this other label.
+			pragma_c([], [pragma_c_raw_code(TraceStmt)],
+				may_call_mercury, yes(Label))
+				- ""
 		]),
 	Code = tree(ProduceCode, TraceCode)
 	},
@@ -243,47 +365,36 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred trace__apply_pre_deaths(trace_port::in, list(var)::in, list(var)::out)
-	is det.
+:- pred trace__build_fail_vars(list(var)::in, list(inst)::in,
+	list(arg_info)::in, module_info::in, list(var)::out) is semidet.
 
-trace__apply_pre_deaths(call, LiveVars, LiveVars).
-trace__apply_pre_deaths(exit, LiveVars, LiveVars).
-trace__apply_pre_deaths(fail, LiveVars, LiveVars).
-trace__apply_pre_deaths(ite_then(_, PreDeaths), LiveVars0, LiveVars) :-
-	set__list_to_set(LiveVars0, LiveVars0Set),
-	set__difference(LiveVars0Set, PreDeaths, LiveVarsSet),
-	set__to_sorted_list(LiveVarsSet, LiveVars).
-trace__apply_pre_deaths(ite_else(_, PreDeaths), LiveVars0, LiveVars) :-
-	set__list_to_set(LiveVars0, LiveVars0Set),
-	set__difference(LiveVars0Set, PreDeaths, LiveVarsSet),
-	set__to_sorted_list(LiveVarsSet, LiveVars).
-trace__apply_pre_deaths(switch(_, PreDeaths), LiveVars0, LiveVars) :-
-	set__list_to_set(LiveVars0, LiveVars0Set),
-	set__difference(LiveVars0Set, PreDeaths, LiveVarsSet),
-	set__to_sorted_list(LiveVarsSet, LiveVars).
-trace__apply_pre_deaths(disj(_, PreDeaths), LiveVars0, LiveVars) :-
-	set__list_to_set(LiveVars0, LiveVars0Set),
-	set__difference(LiveVars0Set, PreDeaths, LiveVarsSet),
-	set__to_sorted_list(LiveVarsSet, LiveVars).
+trace__build_fail_vars([], [], [], _, []).
+trace__build_fail_vars([Var | Vars], [Inst | Insts], [Info | Infos],
+		ModuleInfo, FailVars) :-
+	trace__build_fail_vars(Vars, Insts, Infos, ModuleInfo, FailVars0),
+	Info = arg_info(_Loc, ArgMode),
+	(
+		ArgMode = top_in,
+		\+ inst_is_clobbered(ModuleInfo, Inst)
+	->
+		FailVars = [Var | FailVars0]
+	;
+		FailVars = FailVars0
+	).
 
 %-----------------------------------------------------------------------------%
 
-:- pred trace__port_path(trace_port::in, goal_path::out) is semidet.
-
-trace__port_path(ite_then(Path, _), Path).
-trace__port_path(ite_else(Path, _), Path).
-trace__port_path(switch(Path, _), Path).
-trace__port_path(disj(Path, _), Path).
-
 :- pred trace__port_to_string(trace_port::in, string::out) is det.
 
 trace__port_to_string(call, "MR_PORT_CALL").
 trace__port_to_string(exit, "MR_PORT_EXIT").
 trace__port_to_string(fail, "MR_PORT_FAIL").
-trace__port_to_string(ite_then(_, _), "MR_PORT_THEN").
-trace__port_to_string(ite_else(_, _), "MR_PORT_ELSE").
-trace__port_to_string(switch(_, _),   "MR_PORT_SWITCH").
-trace__port_to_string(disj(_, _),     "MR_PORT_DISJ").
+trace__port_to_string(ite_then, "MR_PORT_THEN").
+trace__port_to_string(ite_else, "MR_PORT_ELSE").
+trace__port_to_string(switch,   "MR_PORT_SWITCH").
+trace__port_to_string(disj,     "MR_PORT_DISJ").
+trace__port_to_string(nondet_pragma_first, "MR_PORT_PRAGMA_FIRST").
+trace__port_to_string(nondet_pragma_later, "MR_PORT_PRAGMA_LATER").
 
 :- pred trace__code_model_to_string(code_model::in, string::out) is det.
 
@@ -334,3 +445,18 @@
 trace__path_step_to_string(ite_else, "e;").
 trace__path_step_to_string(neg, "~;").
 trace__path_step_to_string(exist, "q;").
+
+:- pred trace__convert_external_port_type(external_trace_port::in,
+	trace_port::out) is det.
+
+trace__convert_external_port_type(call, call).
+trace__convert_external_port_type(exit, exit).
+trace__convert_external_port_type(fail, fail).
+
+:- pred trace__convert_nondet_pragma_port_type(nondet_pragma_trace_port::in,
+	trace_port::out) is det.
+
+trace__convert_nondet_pragma_port_type(nondet_pragma_first,
+	nondet_pragma_first).
+trace__convert_nondet_pragma_port_type(nondet_pragma_later,
+	nondet_pragma_later).
diff -u ws4/runtime/mercury_conf.h.date ws2/runtime/mercury_conf.h.date
--- ws4/runtime/mercury_conf.h.date	Wed Apr  8 11:31:23 1998
+++ ws2/runtime/mercury_conf.h.date	Wed Apr  1 15:57:28 1998
@@ -0,0 +1 @@
+datestamp
diff -u ws4/runtime/mercury_conf_param.h ws2/runtime/mercury_conf_param.h
--- ws4/runtime/mercury_conf_param.h	Mon Mar 16 23:23:24 1998
+++ ws2/runtime/mercury_conf_param.h	Tue Mar 31 20:17:55 1998
@@ -90,7 +90,7 @@
 /*
 ** Debugging options:
 **
-** MR_USE_DEBUGGER:
+** MR_USE_EXTERNAL_DEBUGGER:
 **	Make MR_trace() use an external process debugger
 **	(with communication done via a socket interface)
 **	rather than using the debugger that is part of
diff -u ws4/runtime/mercury_goto.h ws2/runtime/mercury_goto.h
--- ws4/runtime/mercury_goto.h	Tue Mar 17 17:38:02 1998
+++ ws2/runtime/mercury_goto.h	Mon Mar 30 18:56:14 1998
@@ -35,22 +35,28 @@
 */
 
 #if defined(MR_INSERT_LABELS)
-  #define	make_label(n, a, l)	make_entry(n, a, l)
+  #define make_label(n, a, l)		make_entry(n, a, l)
+  #define make_label_sl(n, a, l)	make_entry_sl(n, a, l)
 #else
-  #define	make_label(n, a, l)	/* nothing */
+  #define make_label(n, a, l)		/* nothing */
+  #define make_label_sl(n, a, l)	/* nothing */
 #endif
 
 #if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
-  #define make_local(n, a, l)	make_entry(n, a, l)
+  #define make_local(n, a, l)		make_entry(n, a, l)
+  #define make_local_sl(n, a, l)	make_entry_sl(n, a, l)
 #else 
-  #define make_local(n, a, l)	/* nothing */
+  #define make_local(n, a, l)		/* nothing */
+  #define make_local_sl(n, a, l)	/* nothing */
 #endif
 
 #if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS) \
 		|| defined(MR_CHOOSE_ENTRY_POINT)
-  #define make_entry(n, a, l)	insert_entry(n, a, MR_STACK_LAYOUT(l))
+  #define make_entry(n, a, l)		insert_entry(n, a, NULL)
+  #define make_entry_sl(n, a, l)	insert_entry(n, a, MR_STACK_LAYOUT(l))
 #else
-  #define make_entry(n, a, l)	/* nothing */
+  #define make_entry(n, a, l)		/* nothing */
+  #define make_entry_sl(n, a, l)	/* nothing */
 #endif
 
 
@@ -471,6 +477,9 @@
     #define init_entry(label)	\
 	PRETEND_ADDRESS_IS_USED(&&label); \
 	make_entry(stringify(label), label, label)
+    #define init_entry_sl(label)	\
+	PRETEND_ADDRESS_IS_USED(&&label); \
+	make_entry_sl(stringify(label), label, label)
 
     #define ENTRY(label) 	(&label)
     #define STATIC(label) 	(&label)
@@ -498,6 +507,9 @@
     #define init_entry(label)	\
 	make_entry(stringify(label), &&label, label);	\
 	entry(label) = &&label
+    #define init_entry_sl(label)	\
+	make_entry_sl(stringify(label), &&label, label);	\
+	entry(label) = &&label
     #define ENTRY(label) 	(entry(label))
     #define STATIC(label) 	(entry(label))
 
@@ -514,13 +526,17 @@
 	label:	\
 	{
   #define init_local(label)	make_local(stringify(label), &&label, label)
+  #define init_local_sl(label)	make_local_sl(stringify(label), &&label, label)
   #define Define_label(label)	Define_local(label)
   #define Declare_label(label)	/* no declaration required */
   #ifdef MR_INSERT_LABELS
    #define init_label(label)	\
 	make_label(stringify(label), &&entry(label), label)
+   #define init_label_sl(label)	\
+	make_label_sl(stringify(label), &&entry(label), label)
   #else
    #define init_label(label)	make_label(stringify(label), &&label, label)
+   #define init_label_sl(label)	make_label_sl(stringify(label), &&label, label)
   #endif
 
   #define LOCAL(label)		(&&entry(label))
@@ -560,6 +576,7 @@
 	}			\
 	static Code* label(void) {
   #define init_entry(label)	make_entry(stringify(label), label, label)
+  #define init_entry_sl(label)	make_entry_sl(stringify(label), label, label)
 
   #define Declare_local(label)	static Code *label(void)
   #define Define_local(label)	\
@@ -567,6 +584,7 @@
 	}			\
 	static Code* label(void) {
   #define init_local(label)	make_local(stringify(label), label, label)
+  #define init_local_sl(label)	make_local_sl(stringify(label), label, label)
 
   #define Declare_label(label)	static Code *label(void)
   #define Define_label(label)	\
@@ -574,6 +592,7 @@
 	}			\
 	static Code* label(void) {
   #define init_label(label)	make_label(stringify(label), label, label)
+  #define init_label_sl(label)	make_label_sl(stringify(label), label, label)
 
   #define ENTRY(label) 		(label)
   #define STATIC(label) 	(label)
diff -u ws4/runtime/mercury_memory.c ws2/runtime/mercury_memory.c
--- ws4/runtime/mercury_memory.c	Tue Mar 31 12:11:50 1998
+++ ws2/runtime/mercury_memory.c	Thu Apr  2 17:28:07 1998
@@ -80,6 +80,7 @@
 #endif
 
 #include "mercury_imp.h"
+#include "mercury_trace.h"
 
 /*---------------------------------------------------------------------------*/
 
@@ -701,6 +702,7 @@
 	context_msg = explain_context(context);
 	write(STDERR, main_msg, strlen(main_msg));
 	write(STDERR, context_msg, strlen(context_msg));
+	MR_trace_report_raw(STDERR);
 
 	if (dump) {
 		print_dump_stack();
@@ -900,6 +902,7 @@
   #endif
 	fprintf(stderr, "address involved: %p\n", address);
 
+	MR_trace_report(stderr);
 	print_dump_stack();
 	dump_prev_locations();
 	fprintf(stderr, "exiting from signal handler\n");
@@ -990,6 +993,7 @@
 			(void *) info->si_addr);
 	} /* end if */
 
+	MR_trace_report(stderr);
 	print_dump_stack();
 	dump_prev_locations();
 	fprintf(stderr, "exiting from signal handler\n");
@@ -1063,6 +1067,7 @@
 		explain_segv(info, context);
 	}
 
+	MR_trace_report(stderr);
 	print_dump_stack();
 	dump_prev_locations();
 	fprintf(stderr, "exiting from signal handler\n");
diff -u ws4/runtime/mercury_misc.c ws2/runtime/mercury_misc.c
--- ws4/runtime/mercury_misc.c	Tue Apr  7 16:38:35 1998
+++ ws2/runtime/mercury_misc.c	Thu Apr  2 17:28:07 1998
@@ -7,6 +7,7 @@
 #include	"mercury_imp.h"
 #include	"mercury_dlist.h"
 #include	"mercury_regs.h"
+#include	"mercury_trace.h"
 #include	"mercury_misc.h"
 
 #include	<stdio.h>
@@ -468,7 +469,7 @@
 void 
 fatal_error(const char *message) {
 	fprintf(stderr, "Mercury runtime: %s\n", message);
-	MR_trace_report();
+	MR_trace_report(stderr);
 	exit(1);
 }
 
diff -u ws4/runtime/mercury_stack_layout.h ws2/runtime/mercury_stack_layout.h
--- ws4/runtime/mercury_stack_layout.h	Tue Apr  7 16:38:36 1998
+++ ws2/runtime/mercury_stack_layout.h	Tue Mar 31 20:17:18 1998
@@ -53,7 +53,7 @@
 
 #define MR_DETISM_FIRST_SOLN(d)		(((d) & 8) != 0)
 
-#define MR_DETISM_DET_CODE_MODEL(d)	(!MR_DETISM_AT_MOST_MANY(d) \
+#define MR_DETISM_DET_STACK(d)		(!MR_DETISM_AT_MOST_MANY(d) \
 					|| MR_DETISM_FIRST_SOLN(d))
 
 /*
@@ -278,7 +278,7 @@
 	MR_Stack_Layout_Vars	MR_sll_var_info;
 } MR_Stack_Layout_Label;
 
-/* The following macros support obsolete code. */
+/* The following macros support obsolete code (and probably don't work). */
 #define MR_ENTRY_STACK_LAYOUT_GET_LABEL_ADDRESS(s)		\
 		((Code *) field(0, (s), 0))
 
diff -u ws4/runtime/mercury_stack_trace.c ws2/runtime/mercury_stack_trace.c
--- ws4/runtime/mercury_stack_trace.c	Tue Apr  7 16:38:36 1998
+++ ws2/runtime/mercury_stack_trace.c	Tue Apr  7 16:49:11 1998
@@ -51,7 +51,7 @@
 
 		determinism = entry_layout->MR_sle_detism;
 
-		if (MR_DETISM_DET_CODE_MODEL(determinism)) {
+		if (MR_DETISM_DET_STACK(determinism)) {
 			fprintf(stderr, "\t%s\n", label->e_name);
 			if (type == MR_LVAL_TYPE_STACKVAR) {
 				success_pointer = (Code *) field(0, 
diff -u ws4/runtime/mercury_trace.c ws2/runtime/mercury_trace.c
--- ws4/runtime/mercury_trace.c	Tue Apr  7 16:38:37 1998
+++ ws2/runtime/mercury_trace.c	Thu Apr  2 17:28:07 1998
@@ -77,7 +77,8 @@
 ** to manage an interface between the tracer and the user.
 **
 ** MR_trace_cmd says what mode the tracer is in, i.e. what the last
-** trace command was.
+** trace command was. The details of the semantics are given by the
+** code of MR_trace().
 **
 ** MR_trace_seqno is meaningful only when MR_trace_cmd is MR_SKIP or MR_JUMP.
 ** In those cases, it holds the sequence number of the call at whose exit
@@ -85,11 +86,25 @@
 */
 
 typedef enum {
-	MR_CMD_GOTO,
-	MR_CMD_FINISH,
-	MR_CMD_TO_END
+	MR_CMD_GOTO,		/* stop at an event with a given number    */
+	MR_CMD_FINISH,		/* stop when exiting/failing out of a proc */
+	MR_CMD_RESUME_FORWARD,	/* stop at the next non-final port         */
+	MR_CMD_TO_END		/* do not stop until the end of execution  */
 } MR_trace_cmd_type;
 
+#define	MR_NAME_LEN		80
+#define	MR_MAX_SPY_POINTS	20
+#define	MR_LOG10_MAX_SPY_POINTS	20
+
+typedef struct {
+	bool	enabled;
+	char	module_name[MR_NAME_LEN];
+	char	pred_name[MR_NAME_LEN];
+} MR_spy_point;
+
+MR_spy_point	MR_spy_points[MR_MAX_SPY_POINTS];
+int		MR_next_spy_point = 0;
+
 /*
 ** This type must match the definition of classify_request in
 ** library/debugger_interface.m.
@@ -130,8 +145,14 @@
 			const MR_Stack_Layout_Var *var, Word *type_params);
 static int	MR_trace_skip_spaces(int c);
 static void	MR_trace_discard_to_eol(int c);
+static int	MR_trace_get_word(int *c, char word[], int len);
 static void	MR_trace_help(void);
 
+static void	MR_add_spy_point(void);
+static void	MR_list_spy_points(void);
+static void	MR_change_spy_point_status(bool status);
+static bool	MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout);
+
 static Word	MR_trace_make_var_list(MR_trace_port port,
 			const MR_Stack_Layout_Label *layout);
 static Word	MR_trace_lookup_live_lval(MR_Live_Lval locn, bool *succeeded);
@@ -182,8 +203,6 @@
 MR_trace(const MR_Stack_Layout_Label *layout, MR_trace_port port,
 	int seqno, int depth, const char *path, int max_r_num)
 {
-	MR_trace_interact		interact;
-
 	MR_trace_event_number++;
 	switch (MR_trace_cmd) {
 		case MR_CMD_FINISH:
@@ -200,7 +219,19 @@
 			break;
 
 		case MR_CMD_GOTO:
-			if (MR_trace_event_number >= MR_trace_stop_event) {
+			if (MR_trace_event_number >= MR_trace_stop_event
+			|| MR_event_matches_spy_point(layout)) {
+				MR_trace_event(MR_INTERACT, layout,
+					port, seqno, depth, path, max_r_num);
+			} else if (MR_trace_print_intermediate) {
+				MR_trace_event(MR_NO_INTERACT, layout,
+					port, seqno, depth, path, max_r_num);
+			}
+
+			break;
+
+		case MR_CMD_RESUME_FORWARD:
+			if (MR_port_is_final(port)) {
 				MR_trace_event(MR_INTERACT, layout,
 					port, seqno, depth, path, max_r_num);
 			} else if (MR_trace_print_intermediate) {
@@ -208,8 +239,13 @@
 					port, seqno, depth, path, max_r_num);
 			}
 
+			break;
+
 		case MR_CMD_TO_END:
-			if (MR_trace_print_intermediate) {
+			if (MR_event_matches_spy_point(layout)) {
+				MR_trace_event(MR_INTERACT, layout,
+					port, seqno, depth, path, max_r_num);
+			} else if (MR_trace_print_intermediate) {
 				MR_trace_event(MR_NO_INTERACT, layout,
 					port, seqno, depth, path, max_r_num);
 			}
@@ -222,6 +258,25 @@
 	}
 }
 
+static bool
+MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout)
+{
+	const	MR_Stack_Layout_Entry	*entry;
+	int				i;
+
+	entry = layout->MR_sll_entry;
+
+	for (i = 0; i < MR_next_spy_point; i++) {
+		if (streq(MR_spy_points[i].pred_name, entry->MR_sle_name)
+		&& streq(MR_spy_points[i].module_name, entry->MR_sle_def_module)
+		&& MR_spy_points[i].enabled) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
 static void
 MR_trace_event(MR_trace_interact interact,
 	const MR_Stack_Layout_Label *layout, MR_trace_port port,
@@ -229,18 +284,20 @@
 {
 	int	max_mr_num;
 
-	if (max_r_num + MR_NUM_SPECIAL_REG > MR_MAX_SPECIAL_REG_MR)
+	if (max_r_num + MR_NUM_SPECIAL_REG > MR_MAX_SPECIAL_REG_MR) {
 		max_mr_num = max_r_num + MR_NUM_SPECIAL_REG;
-	else
+	} else {
 		max_mr_num = MR_MAX_SPECIAL_REG_MR;
+	}
 
 	MR_copy_regs_to_saved_regs(max_mr_num);
 #ifdef MR_USE_EXTERNAL_DEBUGGER
-	if (MR_trace_debugger == MR_TRACE_EXTERNAL)
+	if (MR_trace_debugger == MR_TRACE_EXTERNAL) {
 		MR_debugger_step(interact, layout, port, seqno, depth, path);
-	else
+	} else {
 		MR_trace_display_user(interact, layout, port, seqno, depth,
 			path);
+	}
 #else
 	/*
 	** We should get here only if MR_trace_debugger == MR_TRACE_INTERNAL.
@@ -282,7 +339,7 @@
 	restore_transient_registers();
 	save_registers();
 
-	for (i = 0; i < max_mr_num; i++) {
+	for (i = 0; i <= max_mr_num; i++) {
 		MR_saved_regs[i] = fake_reg[i];
 	}
 }
@@ -299,7 +356,7 @@
 
 	int i;
 
-	for (i = 0; i < max_mr_num; i++) {
+	for (i = 0; i <= max_mr_num; i++) {
 		fake_reg[i] = MR_saved_regs[i];
 	}
 
@@ -308,16 +365,33 @@
 }
 
 void
-MR_trace_report(void)
+MR_trace_report(FILE *fp)
+{
+	if (MR_trace_event_number > 0) {
+		/*
+		** This means that the executable was compiled with tracing,
+		** which implies that the user wants trace info on abort.
+		*/
+
+		fprintf(fp, "Last trace event was event #%d.\n",
+			MR_trace_event_number);
+	}
+}
+
+void
+MR_trace_report_raw(int fd)
 {
+	char	buf[80];	/* that ought to be more than long enough */
+
 	if (MR_trace_event_number > 0) {
 		/*
 		** This means that the executable was compiled with tracing,
 		** which implies that the user wants trace info on abort.
 		*/
 
-		fprintf(stderr, "Last event was event #%d.\n",
+		sprintf(buf, "Last trace event was event #%d.\n",
 			MR_trace_event_number);
+		write(fd, buf, strlen(buf));
 	}
 }
 
@@ -730,36 +804,43 @@
 	int	count;
 	bool	count_given;
 
-	fflush(stdout);
-	fprintf(stderr, "%8d: %6d %2d ", MR_trace_event_number, seqno, depth);
+	printf("%8d: %6d %2d ", MR_trace_event_number, seqno, depth);
 
 	switch (port) {
 		case MR_PORT_CALL:
-			fprintf(stderr, "CALL ");
+			printf("CALL ");
 			break;
 
 		case MR_PORT_EXIT:
-			fprintf(stderr, "EXIT ");
+			printf("EXIT ");
 			break;
 
 		case MR_PORT_FAIL:
-			fprintf(stderr, "FAIL ");
+			printf("FAIL ");
 			break;
 
 		case MR_PORT_THEN:
-			fprintf(stderr, "THEN ");
+			printf("THEN ");
 			break;
 
 		case MR_PORT_ELSE:
-			fprintf(stderr, "ELSE ");
+			printf("ELSE ");
 			break;
 
 		case MR_PORT_DISJ:
-			fprintf(stderr, "DISJ ");
+			printf("DISJ ");
 			break;
 
 		case MR_PORT_SWITCH:
-			fprintf(stderr, "SWTC ");
+			printf("SWTC ");
+			break;
+
+		case MR_PORT_PRAGMA_FIRST:
+			printf("FRST ");
+			break;
+
+		case MR_PORT_PRAGMA_LATER:
+			printf("LATR ");
 			break;
 
 		default:
@@ -769,39 +850,39 @@
 
 	switch ((int) layout->MR_sll_entry->MR_sle_detism) {
 		case MR_DETISM_DET:
-			fprintf(stderr, "DET   ");
+			printf("DET   ");
 			break;
 
 		case MR_DETISM_SEMI:
-			fprintf(stderr, "SEMI  ");
+			printf("SEMI  ");
 			break;
 
 		case MR_DETISM_NON:
-			fprintf(stderr, "NON   ");
+			printf("NON   ");
 			break;
 
 		case MR_DETISM_MULTI:
-			fprintf(stderr, "MUL   ");
+			printf("MUL   ");
 			break;
 
 		case MR_DETISM_ERRONEOUS:
-			fprintf(stderr, "ERR   ");
+			printf("ERR   ");
 			break;
 
 		case MR_DETISM_FAILURE:
-			fprintf(stderr, "FAIL  ");
+			printf("FAIL  ");
 			break;
 
 		case MR_DETISM_CCNON:
-			fprintf(stderr, "CCNON ");
+			printf("CCNON ");
 			break;
 
 		case MR_DETISM_CCMULTI:
-			fprintf(stderr, "CCMUL ");
+			printf("CCMUL ");
 			break;
 		
 		default:
-			fprintf(stderr, "mercury_trace.c: ???  ");
+			printf("BAD DETERMINISM\n");
 			break;
 	}
 
@@ -811,7 +892,7 @@
 	** not interested in tracing compiler-generated procedures.
 	*/
 
-	fprintf(stderr, "%s:%s/%ld-%ld %s\n",
+	printf("%s:%s/%ld-%ld %s\n",
 		layout->MR_sll_entry->MR_sle_def_module,
 		layout->MR_sll_entry->MR_sle_name,
 		(long) layout->MR_sll_entry->MR_sle_arity,
@@ -819,7 +900,7 @@
 		path);
 
 	while (interact == MR_INTERACT) {
-		fprintf(stderr, "mtrace> ");
+		printf("mtrace> ");
 
 		count = 1;
 		count_given = FALSE;
@@ -858,8 +939,7 @@
 			case 'g':
 				if (! count_given) {
 					MR_trace_discard_to_eol(c);
-					fprintf(stderr, "mtrace: "
-						"no count given\n");
+					printf("mtrace: no count given\n");
 					continue;
 				}
 
@@ -875,8 +955,8 @@
 			case 'f':
 				if (MR_port_is_final(port)) {
 					MR_trace_discard_to_eol(c);
-					fprintf(stderr, "mtrace: this port"
-						"is already final\n");
+					printf("mtrace: this port is "
+						"already final\n");
 					continue;
 				} else {
 					MR_trace_cmd = MR_CMD_FINISH;
@@ -892,8 +972,7 @@
 
 			case 'c':
 				if (count_given)
-					fprintf(stderr, "mtrace: "
-						"count ignored\n");
+					printf("mtrace: count ignored\n");
 
 				MR_trace_cmd = MR_CMD_TO_END;
 				MR_trace_discard_to_eol(c);
@@ -901,8 +980,7 @@
 
 			case 'p':
 				if (count_given)
-					fprintf(stderr, "mtrace: "
-						"count ignored\n");
+					printf("mtrace: count ignored\n");
 
 				MR_trace_discard_to_eol(c);
 				MR_trace_browse((int)
@@ -911,14 +989,59 @@
 
 				continue;
 
+			case 'r':
+				if (count_given)
+					printf("mtrace: count ignored\n");
+
+				MR_trace_cmd = MR_CMD_RESUME_FORWARD;
+				MR_trace_discard_to_eol(c);
+				break;
+
+			case 'b':
+				if (count_given)
+					printf("mtrace: count ignored\n");
+
+				MR_add_spy_point();
+				continue;
+
+			case '?':
+				if (count_given)
+					printf("mtrace: count ignored\n");
+
+				MR_list_spy_points();
+				continue;
+
+			case '+':
+				if (count_given)
+					printf("mtrace: count ignored\n");
+
+				MR_change_spy_point_status(TRUE);
+				continue;
+
+			case '-':
+				if (count_given)
+					printf("mtrace: count ignored\n");
+
+				MR_change_spy_point_status(FALSE);
+				continue;
+
 			case 'a':
 			case EOF:
 				MR_trace_discard_to_eol(c);
-				fprintf(stderr, "mtrace: are you sure"
+				printf("mtrace: are you sure"
 						" you want to abort? ");
 
 				c = MR_trace_skip_spaces(' ');
-				if (c == 'y' | c == EOF) {
+				if (c == 'y' || c == EOF) {
+					/*
+					** We reset MR_trace_event_number
+					** that fatal_error will not
+					** print the last trace event number
+					** (since in this case it is not
+					** meaningful).
+					*/
+
+					MR_trace_event_number = 0;
 					fatal_error("aborting the execution "
 						"on user request");
 				}
@@ -936,6 +1059,77 @@
 	}
 }
 
+static void
+MR_add_spy_point(void)
+{
+	int	c;
+
+	c = getchar();
+
+	if (MR_next_spy_point >= MR_MAX_SPY_POINTS) {
+		MR_trace_discard_to_eol(c);
+		printf("mtrace: no room for more spy points\n");
+		return;
+	}
+
+	if (MR_trace_get_word(&c, MR_spy_points[MR_next_spy_point].module_name,
+			MR_NAME_LEN)
+	&& MR_trace_get_word(&c, MR_spy_points[MR_next_spy_point].pred_name,
+			MR_NAME_LEN)) {
+		MR_trace_discard_to_eol(c);
+		MR_spy_points[MR_next_spy_point].enabled = TRUE;
+		MR_next_spy_point++;
+	}
+	else {
+		printf("usage: \"b module_name pred_name\"\n");
+	}
+}
+
+static void
+MR_list_spy_points(void)
+{
+	int	i;
+
+	for (i = 0; i < MR_next_spy_point; i++) {
+		printf("%2d: %s %s:%s\n", i,
+			MR_spy_points[i].enabled? "+": "-",
+			MR_spy_points[i].module_name,
+			MR_spy_points[i].pred_name);
+	}
+
+	MR_trace_discard_to_eol(getchar());
+}
+
+static void
+MR_change_spy_point_status(bool status)
+{
+	char	buf[MR_LOG10_MAX_SPY_POINTS];
+	int	c;
+	int	i;
+
+	c = getchar();
+
+	if (MR_trace_get_word(&c, buf, MR_LOG10_MAX_SPY_POINTS)) {
+		if (sscanf(buf, "%d", &i) == 1) {
+			if (0 <= i && i < MR_next_spy_point) {
+				MR_spy_points[i].enabled = status;
+			} else {
+				printf("spy point #%d does not exist\n", i);
+			}
+		} else if (strcmp(buf, "*") == 0) {
+			for (i = 0; i < MR_next_spy_point; i++) {
+				MR_spy_points[i].enabled = status;
+			}
+		} else {
+			printf("garbled spy point number\n");
+		}
+	} else {
+		printf("missing spy point number\n");
+	}
+
+	MR_trace_discard_to_eol(c);
+}
+
 static Word
 MR_trace_make_var_list(MR_trace_port port, const MR_Stack_Layout_Label *layout)
 {
@@ -976,7 +1170,9 @@
 		** fails, are not of interest to the trace analyzer.
 		*/
 
-		if (strncmp(name, "TypeInfo", 8) == 0
+		if ((strncmp(name, "TypeInfo", 8) == 0)
+		|| (strncmp(name, "ModuleInfo", 10) == 0)
+		|| (strncmp(name, "HLDS", 4) == 0)
 		|| !MR_trace_get_type_and_value(var, NULL, &type_info, &value))
 		{
 			continue;
@@ -1127,8 +1323,7 @@
 
 	pseudo_type_info = MR_LIVE_TYPE_GET_VAR_TYPE(var->MR_slv_live_type);
 	*type_info = (Word) ML_create_type_info(type_params, pseudo_type_info);
-	*value = MR_trace_lookup_live_lval(var->MR_slv_locn,
-		&succeeded);
+	*value = MR_trace_lookup_live_lval(var->MR_slv_locn, &succeeded);
 	return succeeded;
 }
 
@@ -1145,7 +1340,9 @@
 	** due to the fake arity of the type mercury_builtin:typeinfo/1.
 	*/
 
-	if (strncmp(name, "TypeInfo", 8) == 0)
+	if ((strncmp(name, "TypeInfo", 8) == 0)
+	|| (strncmp(name, "ModuleInfo", 10) == 0)
+	|| (strncmp(name, "HLDS", 4) == 0))
 		return;
 
 	/* The initial blanks are to visually separate */
@@ -1157,6 +1354,8 @@
 		printf("%10s%-21s\t", "", "anonymous variable");
 	}
 
+	fflush(stdout);
+
 	/*
 	** "variables" representing the saved values of succip, hp etc,
 	** which are the "variables" for which get_type_and_value fails,
@@ -1185,13 +1384,13 @@
 		*/
 
 		MR_trace_enabled = FALSE;
-		for (i = 0; i < MAX_FAKE_REG; i++) {
+		for (i = 0; i < MR_MAX_SPECIAL_REG_MR; i++) {
 			fake_reg[i] = MR_saved_regs[i];
 		}
 		restore_registers();
 		r1 = type_info;
 		r2 = value;
-		save_transient_registers(); /* XXX probably redundant now */
+		save_transient_registers(); /* r1 or r2 may be transient */
 		call_engine(MR_library_trace_browser);
 		MR_trace_enabled = TRUE;
 	}
@@ -1215,13 +1414,41 @@
 		c = getchar();
 }
 
+static int
+MR_trace_get_word(int *cptr, char word[], int len)
+{
+	int	c;
+	int	i;
+
+	c = MR_trace_skip_spaces(*cptr);
+
+	i = 0;
+	while (c != EOF && (isalnum(c) || c == '_')) {
+		if (i < len) {
+			word[i++] = c;
+		}
+
+		c = getchar();
+	}
+
+	*cptr = c;
+
+	if (i > 0) {
+		word[i] = '\0';
+		return TRUE;
+	}
+
+	return FALSE;
+}
 
 static void
 MR_trace_help(void)
 {
-	fprintf(stderr, "valid commands are:\n"
+	printf("valid commands are:\n"
 		"a, EOF:\t\t"
 		"\tabort the current execution.\n"
+		"b module pred:\t"
+		"\tset breakpoint in module:pred.\n"
 		"c:\t\t"
 		"\tcontinue to end of program, not printing the trace.\n"
 		"C:\t\t"
@@ -1236,9 +1463,17 @@
 		"\tgo to event #N, printing the trace.\n"
 		"p:\t\t"
 		"\tprint the variables live at this point.\n"
+		"r:\t\t"
+		"\tcontinue until forward execution is resumed.\n"
 		"[<N>] s, [N] CR:"
 		"\tskip N events, not printing the trace.\n"
 		"[<N>] S:\t"
 		"\tskip N events, printing the trace.\n"
+		"?:\t\t"
+		"\tlist all the breakpoints.\n"
+		"+ N:\t\t"
+		"\tenable breakpoint #N.\n"
+		"- N:\t\t"
+		"\tdisable breakpoint #N.\n"
 	);
 }
diff -u ws4/runtime/mercury_trace.h ws2/runtime/mercury_trace.h
--- ws4/runtime/mercury_trace.h	Tue Apr  7 16:38:44 1998
+++ ws2/runtime/mercury_trace.h	Tue Mar 31 20:12:47 1998
@@ -35,7 +35,9 @@
 	MR_PORT_THEN,
 	MR_PORT_ELSE,
 	MR_PORT_DISJ,
-	MR_PORT_SWITCH
+	MR_PORT_SWITCH,
+	MR_PORT_PRAGMA_FIRST,
+	MR_PORT_PRAGMA_LATER
 } MR_trace_port;
 
 extern	void	MR_trace(
@@ -47,11 +49,12 @@
 	int);			/* highest numbered rN register in use */
 
 /*
-** This function will report the number of the last event,
+** These functions will report the number of the last event,
 ** if there have been some events, and will do nothing otherwise.
 */
 
-extern	void	MR_trace_report(void);
+extern	void	MR_trace_report(FILE *fp);
+extern	void	MR_trace_report_raw(int fd);
 
 /*
 ** MR_trace_init() is called from mercury_runtime_init()
diff -u ws4/runtime/mercury_wrapper.c ws2/runtime/mercury_wrapper.c
--- ws4/runtime/mercury_wrapper.c	Tue Apr  7 16:38:45 1998
+++ ws2/runtime/mercury_wrapper.c	Thu Apr  2 17:28:07 1998
@@ -65,10 +65,6 @@
 
 /* other options */
 
-int		r1val = -1;
-int		r2val = -1;
-int		r3val = -1;
-
 bool		check_space = FALSE;
 
 static	bool	benchmark_all_solns = FALSE;
diff -u ws4/runtime/mercury_wrapper.h ws2/runtime/mercury_wrapper.h
--- ws4/runtime/mercury_wrapper.h	Tue Mar 17 17:38:12 1998
+++ ws2/runtime/mercury_wrapper.h	Tue Mar 31 20:25:27 1998
@@ -91,10 +91,6 @@
 /* size of the primary cache */
 extern	size_t		pcache_size;
 
-extern	int		r1val;
-extern	int		r2val;
-extern	int		r3val;
-
 extern	bool		check_space;
 
 /* timing */
--- ws4/library/array.m	Wed Apr  1 18:39:09 1998
+++ ws2/library/array.m	Wed Apr  1 14:43:02 1998
@@ -288,9 +288,9 @@
 Declare_entry(mercury__array__array_compare_3_0);
 
 BEGIN_MODULE(array_module_builtins)
-	init_entry(mercury____Unify___array__array_1_0);
-	init_entry(mercury____Index___array__array_1_0);
-	init_entry(mercury____Compare___array__array_1_0);
+	init_entry_sl(mercury____Unify___array__array_1_0);
+	init_entry_sl(mercury____Index___array__array_1_0);
+	init_entry_sl(mercury____Compare___array__array_1_0);
 BEGIN_CODE
 
 Define_entry(mercury____Unify___array__array_1_0);
diff -u ws4/library/benchmarking.m ws2/library/benchmarking.m
--- ws4/library/benchmarking.m	Wed Apr  8 15:41:28 1998
+++ ws2/library/benchmarking.m	Mon Mar 30 20:10:46 1998
@@ -572,9 +558,9 @@
 Declare_entry(do_call_det_closure);
 
 BEGIN_MODULE(benchmark_nondet_module)
-	init_entry(mercury__benchmarking__benchmark_nondet_5_0);
-	init_label(mercury__benchmarking__benchmark_nondet_5_0_i1);
-	init_label(mercury__benchmarking__benchmark_nondet_5_0_i2);
+	init_entry_sl(mercury__benchmarking__benchmark_nondet_5_0);
+	init_label_sl(mercury__benchmarking__benchmark_nondet_5_0_i1);
+	init_label_sl(mercury__benchmarking__benchmark_nondet_5_0_i2);
 BEGIN_CODE
 
 Define_entry(mercury__benchmarking__benchmark_nondet_5_0);
@@ -662,8 +648,8 @@
 MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__benchmarking__benchmark_det_5_0, 1);
 
 BEGIN_MODULE(benchmark_det_module)
-	init_entry(mercury__benchmarking__benchmark_det_5_0);
-	init_label(mercury__benchmarking__benchmark_det_5_0_i1);
+	init_entry_sl(mercury__benchmarking__benchmark_det_5_0);
+	init_label_sl(mercury__benchmarking__benchmark_det_5_0_i1);
 BEGIN_CODE
 
 Define_entry(mercury__benchmarking__benchmark_det_5_0);
diff -u ws4/library/require.m ws2/library/require.m
--- ws4/library/require.m	Tue Apr  7 16:38:29 1998
+++ ws2/library/require.m	Tue Apr  7 16:47:25 1998
@@ -58,6 +58,7 @@
 :- pragma c_code(error(Message::in), "
 	fflush(stdout);
 	fprintf(stderr, ""Software error: %s\\n"", Message);
+	MR_trace_report(stderr);
 	MR_dump_stack(MR_succip, MR_sp, MR_curfr);
 	exit(1);
 #ifndef USE_GCC_NONLOCAL_GOTOS
diff -u ws4/library/std_util.m ws2/library/std_util.m
--- ws4/library/std_util.m	Tue Apr  7 16:19:46 1998
+++ ws2/library/std_util.m	Tue Apr  7 16:43:50 1998
@@ -501,15 +501,15 @@
 MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__std_util__builtin_aggregate_4_0, 3);
 
 BEGIN_MODULE(builtin_aggregate_module)
-	init_entry(mercury__std_util__builtin_aggregate_4_0);
-	init_entry(mercury__std_util__builtin_aggregate_4_1);
-	init_entry(mercury__std_util__builtin_aggregate_4_2);
-	init_entry(mercury__std_util__builtin_aggregate_4_3);
-	init_entry(mercury__std_util__builtin_aggregate_4_4);
-	init_entry(mercury__std_util__builtin_aggregate_4_5);
-	init_label(mercury__std_util__builtin_aggregate_4_0_i1);
-	init_label(mercury__std_util__builtin_aggregate_4_0_i2);
-	init_label(mercury__std_util__builtin_aggregate_4_0_i3);
+	init_entry_sl(mercury__std_util__builtin_aggregate_4_0);
+	init_entry_sl(mercury__std_util__builtin_aggregate_4_1);
+	init_entry_sl(mercury__std_util__builtin_aggregate_4_2);
+	init_entry_sl(mercury__std_util__builtin_aggregate_4_3);
+	init_entry_sl(mercury__std_util__builtin_aggregate_4_4);
+	init_entry_sl(mercury__std_util__builtin_aggregate_4_5);
+	init_label_sl(mercury__std_util__builtin_aggregate_4_0_i1);
+	init_label_sl(mercury__std_util__builtin_aggregate_4_0_i2);
+	init_label_sl(mercury__std_util__builtin_aggregate_4_0_i3);
 BEGIN_CODE
 
 /*
@@ -1211,14 +1211,14 @@
 MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___std_util__type_info_0_0);
 
 BEGIN_MODULE(unify_univ_module)
-	init_entry(mercury____Unify___std_util__univ_0_0);
-	init_entry(mercury____Index___std_util__univ_0_0);
-	init_entry(mercury____Compare___std_util__univ_0_0);
-	init_label(mercury____Compare___std_util__univ_0_0_i1);
-
-	init_entry(mercury____Unify___std_util__type_info_0_0);
-	init_entry(mercury____Index___std_util__type_info_0_0);
-	init_entry(mercury____Compare___std_util__type_info_0_0);
+	init_entry_sl(mercury____Unify___std_util__univ_0_0);
+	init_entry_sl(mercury____Index___std_util__univ_0_0);
+	init_entry_sl(mercury____Compare___std_util__univ_0_0);
+	init_label_sl(mercury____Compare___std_util__univ_0_0_i1);
+
+	init_entry_sl(mercury____Unify___std_util__type_info_0_0);
+	init_entry_sl(mercury____Index___std_util__type_info_0_0);
+	init_entry_sl(mercury____Compare___std_util__type_info_0_0);
 BEGIN_CODE
 Define_entry(mercury____Unify___std_util__univ_0_0);
 {



More information about the developers mailing list