for review: new debugger command set, part 1

Zoltan Somogyi zs at cs.mu.OZ.AU
Mon Jul 6 19:16:38 AEST 1998


This change implements (most of) this document:

COMMAND SYNTAX

When the debugger (as opposed to the program being debugged) is interacting
with the user, the debugger prints a prompt and reads in a line of text,
which it will interpret as its next command. Each command line consists
of several words separated by white space. The first word is the name of
the command, while any other words give options and/or parameters to the
command.

Some commands take a number as their first parameter. For such commands,
users can type "number command" as well as "command number". The debugger
will internally transform the former into the latter, even if the number
and the command are not separated by white space.

CONCEPTS

break points:
The user may associate a break point with some events that occur inside
a procedure; the invocation condition of the break point says which events
these are. The four possible invocation conditions are: the entry event,
the interface events (the entry, exit and fail events), all events,
and the event at a specific point in the procedure.
The effect of a break point depends on the state of the break point.
If the state of the break point is "stop", execution will stop and user
interaction will start at any event within the procedure that matches the
invocation conditions, unless the current debugger command has specifically
disabled this behavior (see the concept "strict commands" below).
If the state of the break point is "print",
the debugger will print any event within the procedure that matches
the invocation conditions,  unless the current debugger command
has specifically disabled this behavior (see the concept "print level" below).
Neither of these will happen if the break point is disabled.

print level:
When a debugger command steps over some events without user interaction at
those events, the *print level* controls under what circumstances the stepped
over events will be printed. When the print level is "none", none of the
stepped over events will be printed. When the print level is "all", all the
stepped over events will be printed. When the print level is "some",
the debugger will print the event only if a break point applies to the event.
Regardless of the print level, the debugger will print the event that
causes execution to stop and user interaction to start.

strict commands:
When a debugger command steps over some events without user interaction at
those events, the *strictness* of the command controls whether the debugger
will stop execution and resume user interaction at events to which a
break point with state "stop" applies. By default, the debugger will stop
at such events. However, if the debugger is executing a strict command,
it will not stop at an event just because a break point in
the stop state applies to it.

default print level:
The debugger maintains a default print level. The initial value of this
variable is "some", but this value can be overridden by the user.

current environment:
Whenever execution stops at an event, the current environment
is reset to refer to the stack frame of the call specified by the event.
However, the "up", "down" and "level" commands can set the current environment
to refer to one of the ancestors of the current call.
This will then be the current environment until another of these commands
changes the environment yet again or execution continues to another event.

interrupts:
If the debugger recieves an interrupt, it will stop at the next event
regardless of what it command it is executing at the time.
(INTERRUPT HANDLING IS NOT YET IMPLEMENTED.)

FORWARD MOVEMENT COMMANDS

step [-NSans] [<num>]
	If this command is given at event <cur>, continues execution until
	event <cur> + <num>. The default value of <num> is 1.

	The options -n or --none, -s or --some, -a or --all specify
	the print level to use for the duration of the command,
	while the options -S or --strict and -N or --nostrict specify
	the strictness of the command.
	(THE LONG OPTIONS ARE NOT YET IMPLEMENTED.)

	By default, this command is not strict, and it uses the default print
	level.

	A command line containing only a number <num> is interpreted as
	if it were "step <num>".

	An empty command line is interpreted as "step 1".

goto [-NSans] <num>
	Continues execution until event <num> provided that the number
	of the current event is smaller than <num>. Otherwise it reports
	an error.

	The options -n or --none, -s or --some, -a or --all specify
	the print level to use for the duration of the command,
	while the options -S or --strict and -N or --nostrict specify
	the strictness of the command.
	(THE LONG OPTIONS ARE NOT YET IMPLEMENTED.)

	By default, this command is strict and uses the default print level.

finish [-NSans]
	Continues execution until it reaches a final (EXIT or FAIL) port
	of the call to which the current event refers. Reports an error
	if the current event refers to a final port.

	The options -n or --none, -s or --some, -a or --all specify
	the print level to use for the duration of the command,
	while the options -S or --strict and -N or --nostrict specify
	the strictness of the command.
	(THE LONG OPTIONS ARE NOT YET IMPLEMENTED.)

	By default, this command is strict and uses the default print level.

forward [-NSans]
	Continues the program until the program resumes forward execution,
	i.e. until it reaches a non-final port inside any predicate. Reports
	an error if the current event refers to a non-final port.

	The options -n or --none, -s or --some, -a or --all specify
	the print level to use for the duration of the command,
	while the options -S or --strict and -N or --nostrict specify
	the strictness of the command.
	(THE LONG OPTIONS ARE NOT YET IMPLEMENTED.)

	By default, this command is strict and uses the default print level.

continue [-NSans]
	Continues execution until it reaches the end of the program.

	The options -n or --none, -s or --some, -a or --all specify
	the print level to use for the duration of the command,
	while the options -S or --strict and -N or --nostrict specify
	the strictness of the command.
	(THE LONG OPTIONS ARE NOT YET IMPLEMENTED.)

	By default, this command is not strict. The print level used
	by the command by default depends on the final strictness level:
	if the command is strict, it is "none", otherwise it is "some".

BACKWARD MOVEMENT COMMANDS

restart
	Restarts execution at the call port of the call corresponding to the
	current event. Reports an error if the current event does not refer
	to an exit or fail port.

	The command will report an error unless the values of all the input
	arguments are available at the current port. (The compiler will keep
	the values of the input arguments of traced predicates as long as
	possible, but it cannot keep them beyond the point where they are
	destructively updated.) The exception is values of type io__state;
	the debugger can perform a restart if the only missing value is of
	type io__state (there can be only one io__state at any given time).
	(THE EXCEPTION IS NOT YET IMPLEMENTED.)

	a restart has the following effects:

	-	Any input and/or output actions in the repeated code
		will be repeated.

	-	Any file close actions in the repeated code for which the
		corresponding file open action is not also in the repeated
		code may cause later I/O actions referring to the file to fail.

	-	Any file open actions in the repeated code for which the
		corresponding file close action is not also in the repeated
		code may cause later file open actions to fail due to file
		descriptor leak.

	The restriction to exit and fail ports is for implementation reasons:
	only at these ports does the debugger have have enough information
	to figure out how to reset the stacks.

	This limitation can be worked around by letting the program continue
	*forward* execution until it reaches a port on the relevant predicate
	that is outside the commit, and then performing a restart. This
	may require a noticeable amount of time, and may result in the
	execution of I/O and/or other side-effects.

BROWSING COMMANDS

vars
	Prints the names of all the known variables in the current
	environment, together with an ordinal number for each variable.

print <num>
	Prints the value of the variable with the given ordinal number
	in the current environment.

	At the moment this command prints the entire value of the variable,
	even if this is very big. Later it will merely invoke a configurable
	dynamic term browser, which will eventually have its own sublanguage.

print *
	Prints the values of all the known variables in the current environment.

	At the moment this command prints the entire value of every variable,
	even if this is very big. Later it will merely invoke a configurable
	dynamic term browser, which will eventually have its own sublanguage.

stack
	Prints the names of the ancestors of the call specified by the
	current event. If two or more ancestor calls are for the same
	predicate, the procedure identification will be printed once
	with the appropriate multiplicity annotation.

	This command will report an error if there is no stack trace
	information available about any ancestor.

up [<num>]
	Sets the current environment to the stack frame of the <num>'th
	level ancestor of the current environment (the immediate caller
	is the first-level ancestor).

	If <num> is not specified, the default value is one.

	This command will report an error if the current environment
	doesn't have the required number of ancestors, or if there is
	no execution trace information about the requested ancestor,
	or if there is no stack trace information about any of the ancestors
	between the current environment and the requested ancestor.
	(ERROR CHECKING IS NOT YET IMPLEMENTED.)

down [<num>]
	Sets the current environment to the stack frame of the <num>'th
	level descendant of the current environment (the immediate caller
	is the first-level ancestor).

	If <num> is not specified, the default value is one.

	This command will report an error if the current environment
	doesn't have the required number of descendants.
	(ERROR CHECKING IS NOT YET IMPLEMENTED.)

DEBUGGER STATE MANIPULATION COMMANDS

break [-PSaei] <module name> <predicate name> [<arity> [<mode> [<predfunc>]]]
	Puts a break point on the specified procedure.

	The options -P or --print, and -S or --stop specify the action
	to be taken at the break point, while the options -a or --all,
	-e or --entry, and -i or --interface specify the invocation conditions
	of the break point.
	(THE LONG OPTIONS ARE NOT YET IMPLEMENTED.)

	By default, the initial action of the break point is "stop",
	and its invocation condition is "interface".

break [-PS] here
	Puts a break point on the procedure referred to by the current event,
	with the invocation condition being the event at the current location
	in the procedure body.

	The options -P or --print, and -S or --stop specify the action
	to be taken at the break point.
	(THE LONG OPTIONS, AND CHECKING FOR THE ABSENCE OF -AEI
	ARE NOT YET IMPLEMENTED.)

	By default, the initial state of the break point is "stop".

break info
	Lists the details and status of all break points.

enable <num>
	Enables the break point with the given number.
	Reports an error if there is no break point with that number.

enable *
	Enables all break points.

disable <num>
	Disables the break point with the given number.
	Reports an error if there is no break point with that number.

disable *
	Disables all break points.

MISCELLANEOUS COMMANDS

printlevel [<printlevel>]
	If the argument is present, sets the default print level
	to the named level. If it is absent, reports the current default
	print level.

echo [on | off]
	If the argument is present, turns the echoing of commands on or off.
	to the named level. If it is absent, reports whether commands are
	being echoed or not.

scroll [on | off]
	If the argument is present, turn user control over the scrolling
	of sequences of event reports on or off. If it is absent, reports
	whether user scroll control is enabled or not.

	When user scroll control is enabled, every 20th report of an event
	will be followed by a --more-- prompt. The user may type an empty
	line, which allows the debugger to continue to print the next batch
	of event reports. By typing a line that starts with "a", "s" or "n",
	the user can override the print level of the current command, setting
	it to "all", "some" or "none" respectively. By typing a line that
	starts with "q", the user can abort the current command and get back
	control at the next event.

help
	Prints information about the available commands.

quit
	Quits the debugger and aborts the execution of the program.
	Asks confirmation first, which is given by any answer starting
	with "y" or EOF.

	EOF on the debugger's input is considered a quit command.

---------------------------------------------------------------------------

Estimated hours taken: 32

Move the debugger command set a large step towards the proposal previously
circulated.

compiler/trace.m:
	After every call to MR_trace(), emit code that checks whether it
	should jump away, and if yes, performs the jump. This is used to
	implement restart. (The debugger cannot execute the jump itself
	because it is in the wrong C stack frame.)

	Allocate a stack slot to hold the number of the call event, and fill
	this slot. This is used at restart to reset the event counter.

compiler/llds.m:
compiler/continuation_info.m:
	Modify the data structures that record information about live
	value at program points, to record the identity of each variable.
	This is necessary for the implementation of the restart command,
	since we do not want to confuse two distinct variables just because
	they have the same name.

	Clean up the data structure a bit, so that we don't have to store
	dummy names for values that are not variables.

compiler/continuation_info.m:
compiler/stack_layout.m:
	Changes required to record the location of the stack slot holding
	the event number, and to emit this info in the proc layout.

compiler/*.m:
	Minor changes to conform to these data structure changes.

compiler/stack_layout.m:
	Include the variable number as a prefix in variable names. For
	example, a variable whose name is X and number is 5 is recorded
	in the name array as "5:X".

compiler/call_gen.m:
	Fix a bug: in the presence of execution tracing but the absence
	of accurate gc, information about the variables that are live
	at the call return wasn't being gathered properly.

runtime/mercury_label.c:
	Initialize the tables before use.

runtime/mercury_memory.c:
runtime/mercury_wrapper.h:
runtime/mercury_stack_trace.c:
	Stylistic fixes.

runtime/mercury_misc.c:
runtime/mercury_overflow.h:
	Update several obsolete zone references.

runtime/mercury_engine.h:
	Add a macro to make references to the detstack and nondetstack
	zones easier.

runtime/mercury_stack_trace.[ch]:
	Factor out the code that prints the id of a procedure into a function
	of its own, so that it can also be used from the debugger, ensuring
	appearance commonality.

runtime/mercury_stack_layout.h:
	Add the field holding the slot number of the call event number
	to MR_Stack_Layout_Entry, and add a macro to make it more convenient
	to disentangle the real variablee name from the number:name pair.

runtime/mercury_trace_internal.c:
	Implement most of the proposed command set. Command names are now
	words, and several commands now have options (only single-character
	options for now) allowing the user to override the default print level
	or strictness of the command, or the invocation conditions or action
	of a break point. Allows control over command echoing and the
	scrolling of sequences of event reports.

runtime/mercury_trace.[ch]:
	If MR_TRACE_HISTOGRAM is defined, record a count of the number of
	events at each depth. This information can help us evaluate space-time
	tradeoffs.

	Extend the trace controls to support the new functionalities
	required by the new debugger language, which are print levels
	and variable-strictness commands.

	Pass the command structure to MR_trace_event_report, since
	the user can now forcibly terminate the scrolling of reports.

runtime/mercury_trace_base.[ch]:
	Define the data structures for the histogram, and print the histogram
	when a traced program exits.

runtime/mercury_trace_spy.[ch]:
	New module to manage break points. The test of whether an event
	matches a break point is now much more efficient than before.
	The new module also allows several breakpoints with different
	actions and different invocation conditions (e.g. all ports,
	entry port, interface ports or specific (possibly internal) port)
	to be defined on the same procedure.

runtime/mercury_trace_tables.[ch]:
	New module to manage a table of the debuggable modules, in which
	each such module is linked to the list of the layouts of all the
	procedures defined in that module. This information allows the
	debugger to turn the name of predicate/function (possibly together
	with its arity and mode number) into the procedure layout structure
	required by the spy point module. Eventually it may also be useful
	in supplying lists of identifiers for command line completion.

	Modules for which no stack layout information is available will
	not be included in the table, since do_init_modules will not
	register any labels for them in the label table.

runtime/mercury_trace_util.[ch]:
	Add a new auxiliary function used to implement restart.

runtime/mercury_trace*.[ch]:
	Make typedef'd names conform to the naming convention.

runtime/Mmakefile:
	Include the new modules in the library.

tests/debugger/*.inp:
	Update the inputs to all the debugger test cases to use the new
	command set.

	Updates to the expected output files will follow later.

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 bytecode
cvs diff: Diffing bytecode/test
cvs diff: Diffing compiler
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.122
diff -u -u -r1.122 call_gen.m
--- call_gen.m	1998/05/16 07:29:43	1.122
+++ call_gen.m	1998/07/05 06:18:11
@@ -765,37 +765,47 @@
 		LiveVals0),
 	code_info__get_globals(Globals),
 	{ globals__get_gc_method(Globals, GC_Method) },
-	call_gen__insert_arg_livelvals(OutputArgs, GC_Method, AfterCallInstMap,
-		LiveVals0, LiveVals).
-	
+	{ globals__get_trace_level(Globals, TraceLevel) },
+	{
+		( GC_Method = accurate
+		; trace_level_trace_returns(TraceLevel, yes)
+		)
+	->
+		NeedVarInfo = yes
+	;
+		NeedVarInfo = no
+	},
+	call_gen__insert_arg_livelvals(OutputArgs, NeedVarInfo,
+		AfterCallInstMap, LiveVals0, LiveVals).
 
 % Maybe a varlist to type_id list would be a better way to do this...
 
 %---------------------------------------------------------------------------%
 
-:- pred call_gen__insert_arg_livelvals(list(pair(var, arg_loc)), gc_method, 
+:- pred call_gen__insert_arg_livelvals(list(pair(var, arg_loc)), bool, 
 	instmap, list(liveinfo), list(liveinfo), code_info, code_info).
 :- mode call_gen__insert_arg_livelvals(in, in, in, in, out, in, out) is det.
 
 call_gen__insert_arg_livelvals([], _, _, LiveVals, LiveVals) --> [].
-call_gen__insert_arg_livelvals([Var - L | As], GC_Method, AfterCallInstMap, 
+call_gen__insert_arg_livelvals([Var - L | As], NeedVarInfo, AfterCallInstMap, 
 		LiveVals0, LiveVals) -->
 	code_info__get_varset(VarSet),
 	{ varset__lookup_name(VarSet, Var, Name) },
 	(
-		{ GC_Method = accurate }
+		{ NeedVarInfo = yes }
 	->
 		{ instmap__lookup_var(AfterCallInstMap, Var, Inst) },
 
 		code_info__variable_type(Var, Type),
 		{ type_util__vars(Type, TypeVars) },
 		code_info__find_type_infos(TypeVars, TypeParams),
-		{ LiveVal = live_lvalue(R, var(Type, Inst), Name, TypeParams) }
+		{ VarInfo = var(Var, Name, Type, Inst) },
+		{ LiveVal = live_lvalue(R, VarInfo, TypeParams) }
 	;
-		{ LiveVal = live_lvalue(R, unwanted, Name, []) }
+		{ LiveVal = live_lvalue(R, unwanted, []) }
 	),
 	{ code_util__arg_loc_to_register(L, R) },
-	call_gen__insert_arg_livelvals(As, GC_Method, AfterCallInstMap, 
+	call_gen__insert_arg_livelvals(As, NeedVarInfo, AfterCallInstMap, 
 		[LiveVal | LiveVals0], LiveVals).
 
 %---------------------------------------------------------------------------%
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.52
diff -u -u -r1.52 code_gen.m
--- code_gen.m	1998/06/18 06:05:48	1.52
+++ code_gen.m	1998/07/06 09:09:10
@@ -218,7 +218,7 @@
 		CodeInfo1 = CodeInfo0
 	),
 	generate_category_code(CodeModel, Goal, ProcInfo, CodeTree,
-		MaybeTraceCallLabel, FrameInfo, CodeInfo1, CodeInfo),
+		MaybeCallInfo, FrameInfo, CodeInfo1, CodeInfo),
 		% extract the new continuation_info and cell count
 	code_info__get_cell_count(CellCount, CodeInfo, _CodeInfo1),
 
@@ -240,7 +240,7 @@
 		code_info__get_layout_info(LayoutInfo, CodeInfo, _CodeInfo2),
 		continuation_info__add_proc_info(proc(PredId, ProcId),
 			ProcLabel, TotalSlots, Detism, MaybeSuccipSlot,
-			MaybeTraceCallLabel, LayoutInfo, ContInfo0, ContInfo)
+			MaybeCallInfo, LayoutInfo, ContInfo0, ContInfo)
 	;
 		ContInfo = ContInfo0
 	),
@@ -297,11 +297,11 @@
 	% for the failure continuation at all times.)
 
 :- pred generate_category_code(code_model, hlds_goal, proc_info, code_tree,
-	maybe(label), frame_info, code_info, code_info).
+	maybe(pair(label, lval)), frame_info, code_info, code_info).
 :- mode generate_category_code(in, in, in, out, out, out, in, out) is det.
 
 generate_category_code(model_det, Goal, ProcInfo, Code,
-		MaybeTraceCallLabel, FrameInfo) -->
+		MaybeCallInfo, FrameInfo) -->
 		% generate the code for the body of the clause
 	(
 		code_info__get_globals(Globals),
@@ -309,7 +309,7 @@
 		middle_rec__match_and_generate(Goal, MiddleRecCode)
 	->
 		{ Code = MiddleRecCode },
-		{ MaybeTraceCallLabel = no },
+		{ MaybeCallInfo = no },
 		{ FrameInfo = frame(0, no, no) }
 	;
 		% make a new failure cont (not model_non);
@@ -326,10 +326,11 @@
 			code_info__push_resume_point_vars(ResumeVars),
 			trace__generate_external_event_code(call, TraceInfo,
 				TraceCallLabel, _TypeInfos, TraceCallCode),
-			{ MaybeTraceCallLabel = yes(TraceCallLabel) }
+			{ trace__get_event_num_slot(TraceInfo, EventNumSlot) },
+			{ MaybeCallInfo = yes(TraceCallLabel - EventNumSlot) }
 		;
 			{ TraceCallCode = empty },
-			{ MaybeTraceCallLabel = no }
+			{ MaybeCallInfo = no }
 		),
 		code_gen__generate_goal(model_det, Goal, BodyCode),
 		code_gen__generate_entry(model_det, Goal, FrameInfo,
@@ -344,7 +345,7 @@
 	).
 
 generate_category_code(model_semi, Goal, ProcInfo, Code,
-		MaybeTraceCallLabel, FrameInfo) -->
+		MaybeCallInfo, FrameInfo) -->
 		% make a new failure cont (not model_non)
 	code_info__manufacture_failure_cont(no),
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
@@ -362,7 +363,8 @@
 		code_info__push_resume_point_vars(ResumeVars),
 		trace__generate_external_event_code(call, TraceInfo,
 			TraceCallLabel, _TypeInfos, TraceCallCode),
-		{ MaybeTraceCallLabel = yes(TraceCallLabel) },
+		{ trace__get_event_num_slot(TraceInfo, EventNumSlot) },
+		{ MaybeCallInfo = yes(TraceCallLabel - EventNumSlot) },
 		code_gen__generate_goal(model_semi, Goal, BodyCode),
 		code_gen__generate_entry(model_semi, Goal, FrameInfo,
 			EntryCode),
@@ -385,7 +387,7 @@
 			     FailCode))))))))
 		}
 	;
-		{ MaybeTraceCallLabel = no },
+		{ MaybeCallInfo = no },
 		code_gen__generate_goal(model_semi, Goal, BodyCode),
 		code_gen__generate_entry(model_semi, Goal, FrameInfo,
 			EntryCode),
@@ -403,7 +405,7 @@
 	).
 
 generate_category_code(model_non, Goal, ProcInfo, Code,
-		MaybeTraceCallLabel, FrameInfo) -->
+		MaybeCallInfo, FrameInfo) -->
 		% make a new failure cont (yes, it is model_non)
 	code_info__manufacture_failure_cont(yes),
 		% we must arrange the tracing of failure out of this proc
@@ -416,7 +418,8 @@
 		code_info__push_resume_point_vars(ResumeVars),
 		trace__generate_external_event_code(call, TraceInfo,
 			TraceCallLabel, _TypeInfos, TraceCallCode),
-		{ MaybeTraceCallLabel = yes(TraceCallLabel) },
+		{ trace__get_event_num_slot(TraceInfo, EventNumSlot) },
+		{ MaybeCallInfo = yes(TraceCallLabel - EventNumSlot) },
 		code_gen__generate_goal(model_non, Goal, BodyCode),
 		code_gen__generate_entry(model_non, Goal, FrameInfo,
 			PrologCode),
@@ -439,7 +442,7 @@
 			     FailCode)))))))
 		}
 	;
-		{ MaybeTraceCallLabel = no },
+		{ MaybeCallInfo = no },
 		code_gen__generate_goal(model_non, Goal, BodyCode),
 		code_gen__generate_entry(model_non, Goal, FrameInfo,
 			PrologCode),
@@ -1219,7 +1222,7 @@
 		Instrn0 = call(Target, ReturnLabel, LiveVals0, CM)
 	->
 		Instrn  = call(Target, ReturnLabel, 
-			[live_lvalue(stackvar(StackLoc), succip, "", []) |
+			[live_lvalue(stackvar(StackLoc), succip, []) |
 			LiveVals0], CM)
 	;
 		Instrn = Instrn0
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.223
diff -u -u -r1.223 code_info.m
--- code_info.m	1998/06/18 06:05:53	1.223
+++ code_info.m	1998/07/05 06:00:01
@@ -2910,7 +2910,7 @@
 
 code_info__generate_temp_livelvals([], LiveInfo, LiveInfo).
 code_info__generate_temp_livelvals([Slot - StoredLval | Slots], LiveInfo0, 
-		[live_lvalue(Slot, LiveValueType, "", []) | LiveInfo1]) :-
+		[live_lvalue(Slot, LiveValueType, []) | LiveInfo1]) :-
 	code_info__get_live_value_type(StoredLval, LiveValueType),
 	code_info__generate_temp_livelvals(Slots, LiveInfo0, LiveInfo1).
 
@@ -2935,11 +2935,11 @@
 		code_info__get_live_value_type(lval(maxfr), MaxfrValueType),
 		code_info__get_live_value_type(lval(redoip(lval(maxfr))),
 			RedoipValueType),
-		LiveInfo2 = [live_lvalue(CurfrVar, CurfrValueType, "", []) | 
+		LiveInfo2 = [live_lvalue(CurfrVar, CurfrValueType, []) | 
 				LiveInfo1],
-		LiveInfo3 = [live_lvalue(MaxfrVar, MaxfrValueType, "", []) |
+		LiveInfo3 = [live_lvalue(MaxfrVar, MaxfrValueType, []) |
 				LiveInfo2],
-		LiveInfo  = [live_lvalue(RedoipVar, RedoipValueType, "", []) |
+		LiveInfo  = [live_lvalue(RedoipVar, RedoipValueType, []) |
 				LiveInfo3]
 	).
 
@@ -2960,10 +2960,10 @@
 		code_info__variable_type(Var, Type),
 		{ type_util__vars(Type, TypeVars) },
 		code_info__find_type_infos(TypeVars, TypeParams),
-		{ LiveLval = live_lvalue(Lval, var(Type, Inst), Name,
+		{ LiveLval = live_lvalue(Lval, var(Var, Name, Type, Inst),
 			TypeParams) }
 	;
-		{ LiveLval = live_lvalue(Lval, unwanted, Name, []) }
+		{ LiveLval = live_lvalue(Lval, unwanted, []) }
 	),
 	code_info__livevals_to_livelvals(Ls, NeedVarInfo, AfterCallInstMap, 
 		Lives).
Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.13
diff -u -u -r1.13 continuation_info.m
--- continuation_info.m	1998/06/18 06:06:04	1.13
+++ continuation_info.m	1998/07/06 09:05:07
@@ -63,18 +63,23 @@
 	%
 :- type proc_layout_info
 	--->	proc_layout_info(
-			proc_label,	% the proc label
-			determinism,	% determines which stack is used
-			int,		% number of stack slots
-			maybe(int),	% location of succip on stack
-			maybe(label),	% if generate_trace is set,
+			proc_label,	% The proc label.
+			determinism,	% Determines which stack is used.
+			int,		% Number of stack slots.
+			maybe(int),	% Location of succip on stack.
+			maybe(pair(label,lval)),
+					% If generate_trace is set,
 					% this contains the label associated
 					% with the call event, whose stack
 					% layout says which variables were
-					% live and where on entry
+					% live and where on entry, and the
+					% number of the stack slot that holds
+					% the event number of the call event.
+					% Both are used in implementing
+					% the debugger's restart command.
 			proc_label_layout_info
-					% info for each internal label,
-					% needed for basic_stack_layouts
+					% Info for each internal label,
+					% needed for basic_stack_layouts.
 		).
 
 	%
@@ -123,8 +128,8 @@
 	%   of the variables agc is interested in (the named subset).
 	%   We do not collect this set explicitly. Instead, if we are doing
 	%   execution tracing, we collect agc layout info as usual, and
-	%   (if we not really doing agc) remove the unnamed variables
-	%   in stack_layout.m.
+%   (if we not really doing agc) remove the unnamed variables
+%   in stack_layout.m.
 	%
 	% For labels which correspond to a trace port (part (a) above),
 	% we record information in the first field. Since trace.m generates
@@ -159,8 +164,7 @@
 :- type var_info
 	--->	var_info(
 			lval,		% the location of the variable
-			live_value_type,% pseudo-typeinfo giving the var's type
-			string		% the var's name
+			live_value_type % info about the variable
 		).
 
 	% Return an initialized continuation info structure.
@@ -175,7 +179,7 @@
 	% in this proc (if there is one).
 	%
 :- pred continuation_info__add_proc_info(pred_proc_id::in, proc_label::in,
-	int::in, determinism::in, maybe(int)::in, maybe(label)::in,
+	int::in, determinism::in, maybe(int)::in, maybe(pair(label, lval))::in,
 	proc_label_layout_info::in, continuation_info::in,
 	continuation_info::out) is det.
 
@@ -227,13 +231,13 @@
 	% continuation_info. 
 	%
 continuation_info__add_proc_info(PredProcId, ProcLabel, StackSize,
-		Detism, SuccipLocation, MaybeTraceCallLabel, InternalMap,
+		Detism, SuccipLocation, MaybeCallInfo, InternalMap,
 		ContInfo0, ContInfo) :-
 	( map__contains(ContInfo0, PredProcId) ->
 		error("duplicate continuation_info for proc.")
 	;
 		LayoutInfo = proc_layout_info(ProcLabel, Detism, StackSize,
-			SuccipLocation, MaybeTraceCallLabel, InternalMap),
+			SuccipLocation, MaybeCallInfo, InternalMap),
 		map__det_insert(ContInfo0, PredProcId, LayoutInfo, ContInfo)
 	).
 
@@ -320,12 +324,12 @@
 
 continuation_info__convert_return_data(LiveInfos, VarInfoSet, TypeInfoSet) :-
 	GetVarInfo = lambda([LiveLval::in, VarInfo::out] is det, (
-		LiveLval = live_lvalue(Lval, LiveValueType, Name, _),
-		VarInfo = var_info(Lval, LiveValueType, Name)
+		LiveLval = live_lvalue(Lval, LiveValueType, _),
+		VarInfo = var_info(Lval, LiveValueType)
 	)),
 	list__map(GetVarInfo, LiveInfos, VarInfoList),
 	GetTypeInfo = lambda([LiveLval::in, TypeInfos::out] is det, (
-		LiveLval = live_lvalue(_, _, _, TypeInfos)
+		LiveLval = live_lvalue(_, _, TypeInfos)
 	)),
 	list__map(GetTypeInfo, LiveInfos, TypeInfoListList),
 	list__condense(TypeInfoListList, TypeInfoList),
@@ -340,7 +344,8 @@
 continuation_info__filter_named_vars([LiveInfo | LiveInfos], Filtered) :-
 	continuation_info__filter_named_vars(LiveInfos, Filtered1),
 	(
-		LiveInfo = live_lvalue(_, _, Name, _),
+		LiveInfo = live_lvalue(_, LiveType, _),
+		LiveType = var(_, Name, _, _),
 		Name \= ""
 	->
 		Filtered = [LiveInfo | Filtered1]
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.225
diff -u -u -r1.225 llds.m
--- llds.m	1998/06/09 02:13:21	1.225
+++ llds.m	1998/07/05 05:43:34
@@ -401,10 +401,6 @@
 				% refer to?
 			live_value_type,
 				% What is the type of this live value?
-			string,
-				% What is the name of the variable stored here?
-				% The empty string if this lval does not
-				% store a variable.
 			assoc_list(tvar, lval)
 				% Where are the typeinfos that determine the
 				% types of the actual parameters of the type
@@ -416,15 +412,15 @@
 	% live_value_type describes the different sorts of data that
 	% can be considered live.
 :- type live_value_type 
-	--->	succip		% a stored succip
-	;	curfr		% a stored curfr
-	;	maxfr		% a stored maxfr
-	;	redoip
-	;	hp
-	;	var(type, inst)	% a variable
-	;	unwanted.	% something we don't need, or used as
-				% a placeholder for non-accurate gc.
-	
+	--->	succip				% a stored succip
+	;	curfr				% a stored curfr
+	;	maxfr				% a stored maxfr
+	;	redoip				% a stored redoip
+	;	hp				% a stored head pointer
+	;	var(var, string, type, inst)	% a variable
+	;	unwanted.			% something we don't need,
+						% or at least don't need
+						% information about
 
 	% An lval represents a data location or register that can be used
 	% as the target of an assignment.
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.84
diff -u -u -r1.84 llds_out.m
--- llds_out.m	1998/06/18 06:06:32	1.84
+++ llds_out.m	1998/07/05 06:00:59
@@ -1473,12 +1473,10 @@
 
 output_gc_livevals_2([]) --> [].
 output_gc_livevals_2([LiveInfo | LiveInfos]) -->
-	{ LiveInfo = live_lvalue(Lval, LiveValueType, Name, TypeParams) },
+	{ LiveInfo = live_lvalue(Lval, LiveValueType, TypeParams) },
 	io__write_string(" *\t"),
 	output_lval(Lval),
 	io__write_string("\t"),
-	io__write_string(Name),
-	io__write_string("\t"),
 	output_live_value_type(LiveValueType),
 	io__write_string("\t"),
 	output_gc_livevals_params(TypeParams),
@@ -1506,8 +1504,10 @@
 output_live_value_type(redoip) --> io__write_string("MR_redoip").
 output_live_value_type(hp) --> io__write_string("MR_hp").
 output_live_value_type(unwanted) --> io__write_string("unwanted").
-output_live_value_type(var(Type, Inst)) --> 
+output_live_value_type(var(_, Name, Type, Inst)) --> 
 	io__write_string("var("),
+	io__write_string(Name),
+	io__write_string(", "),
 	{ varset__init(NewVarset) },
 	mercury_output_term(Type, NewVarset, no),
 	io__write_string(", "),
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.14
diff -u -u -r1.14 stack_layout.m
--- stack_layout.m	1998/06/18 06:06:49	1.14
+++ stack_layout.m	1998/07/06 10:18:41
@@ -66,15 +66,21 @@
 % The meanings of the fields in both forms are the same as in procedure labels.
 %
 % If the option trace_stack_layout is set, i.e. if we are doing execution
-% tracing, the table will also include one extra field:
+% tracing, the table will also include two extra fields:
 %
 %	call trace info		(Word *) - pointer to label stack layout
+%	call event number	(Integer) - stack slot number storing the
+%					event number of the call event
 %
-% This will point to the per-label layout info for the label associated
+% The first will point to the per-label layout info for the label associated
 % with the call event at the entry to the procedure. The purpose of this
 % information is to allow the runtime debugger to find out which variables
 % are where on entry, so it can reexecute the procedure if asked to do so
 % and if the values of the required variables are still available.
+% The second field allows the debugger to find the event number of the
+% call event, so that if the user asks for the call to be restarted,
+% the restarted execution will use the same event numbers as the original
+% execution.
 %
 % If the option basic_stack_layout is set, we generate stack layout tables
 % for some labels internal to the procedure. This table will be stored in the
@@ -218,9 +224,9 @@
 
 stack_layout__construct_layouts(ProcLayoutInfo) -->
 	{ ProcLayoutInfo = proc_layout_info(ProcLabel, Detism,
-		StackSlots, SuccipLoc, CallLabel, InternalMap) },
+		StackSlots, SuccipLoc, CallInfo, InternalMap) },
 	stack_layout__construct_proc_layout(ProcLabel, Detism,
-		StackSlots, SuccipLoc, CallLabel),
+		StackSlots, SuccipLoc, CallInfo),
 	{ map__to_assoc_list(InternalMap, Internals) },
 	list__foldl(stack_layout__construct_internal_layout(ProcLabel),
 		Internals).
@@ -230,11 +236,11 @@
 	% Construct a procedure-specific layout.
 
 :- pred stack_layout__construct_proc_layout(proc_label::in,
-	determinism::in, int::in, maybe(int)::in, maybe(label)::in,
+	determinism::in, int::in, maybe(int)::in, maybe(pair(label, lval))::in,
 	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__construct_proc_layout(ProcLabel, Detism, StackSlots,
-		MaybeSuccipLoc, MaybeCallLabel) -->
+		MaybeSuccipLoc, MaybeCallInfo) -->
 	{
 		MaybeSuccipLoc = yes(Location0)
 	->
@@ -297,11 +303,20 @@
 	(
 		{ TraceLayout = yes }
 	->
-		( { MaybeCallLabel = yes(CallLabel) } ->
+		( { MaybeCallInfo = yes(CallLabel - EventNumLval) } ->
 			{ CallRval = yes(const(data_addr_const(
 				data_addr(ModuleName,
 					stack_layout(CallLabel))))) },
-			{ list__append(MaybeRvals1, [CallRval], MaybeRvals) }
+			{ EventNumLval = stackvar(Stackvar) ->
+				SlotNumber = Stackvar
+			; EventNumLval = framevar(Framevar) ->
+				SlotNumber = Framevar
+			;
+				error("event number is not in stack slot")
+			},
+			{ EventNumRval = yes(const(int_const(SlotNumber))) },
+			{ list__append(MaybeRvals1, [CallRval, EventNumRval],
+				MaybeRvals) }
 		;
 			{ error("stack_layout__construct_proc_layout: call label not present") }
 		)
@@ -491,8 +506,8 @@
 
 stack_layout__select_trace_return(Infos, TVars, TraceReturnInfos, TVars) :-
 	IsNamedReturnVar = lambda([LvalInfo::in] is semidet, (
-		LvalInfo = var_info(Lval, LvalType, Name),
-		LvalType = var(_, _),
+		LvalInfo = var_info(Lval, LvalType),
+		LvalType = var(_, Name, _, _),
 		Name \= "",
 		( Lval = stackvar(_) ; Lval = framevar(_) )
 	)),
@@ -513,14 +528,16 @@
 
 stack_layout__sort_livevals(OrigInfos, FinalInfos) :-
 	IsNamedVar = lambda([LvalInfo::in] is semidet, (
-		LvalInfo = var_info(_Lval, LvalType, Name),
-		LvalType = var(_, _),
+		LvalInfo = var_info(_Lval, LvalType),
+		LvalType = var(_, Name, _, _),
 		Name \= ""
 	)),
 	list__filter(IsNamedVar, OrigInfos, NamedVarInfos0, OtherInfos0),
 	CompareVarInfos = lambda([Var1::in, Var2::in, Result::out] is det, (
-		Var1 = var_info(Lval1, _, Name1),
-		Var2 = var_info(Lval2, _, Name2),
+		Var1 = var_info(Lval1, LiveType1),
+		Var2 = var_info(Lval2, LiveType2),
+		stack_layout__get_name_from_live_value_type(LiveType1, Name1),
+		stack_layout__get_name_from_live_value_type(LiveType2, Name2),
 		compare(NameResult, Name1, Name2),
 		( NameResult = (=) ->
 			compare(Result, Lval1, Lval2)
@@ -532,6 +549,16 @@
 	list__sort(CompareVarInfos, OtherInfos0, OtherInfos),
 	list__append(NamedVarInfos, OtherInfos, FinalInfos).
 
+:- pred stack_layout__get_name_from_live_value_type(live_value_type::in,
+	string::out) is det.
+
+stack_layout__get_name_from_live_value_type(LiveType, Name) :-
+	( LiveType = var(_, NamePrime, _, _) ->
+		Name = NamePrime
+	;
+		Name = ""
+	).
+
 %---------------------------------------------------------------------------%
 
 	% Given a association list of type variables and their locations
@@ -589,7 +616,7 @@
 	list(maybe(rval))::out, stack_layout_info::in, stack_layout_info::out)
 	is det.
 
-stack_layout__construct_liveval_pair(var_info(Lval, LiveValueType, _),
+stack_layout__construct_liveval_pair(var_info(Lval, LiveValueType),
 		MaybeRvals) -->
 	{ stack_layout__represent_lval(Lval, Rval0) },
 	stack_layout__represent_live_value_type(LiveValueType, Rval1),
@@ -598,13 +625,19 @@
 :- pred stack_layout__construct_liveval_name(var_info::in, maybe(rval)::out)
 	is det.
 
-stack_layout__construct_liveval_name(var_info(_, _, Name), MaybeRval) :-
-	( Name = "" ->
+stack_layout__construct_liveval_name(var_info(_, VarInfo), MaybeRval) :-
+	(
+		VarInfo = var(Var, Name, _, _),
+		Name \= ""
+	->
+		term__var_to_int(Var, Int),
+		string__int_to_string(Int, IntStr),
+		string__append_list([IntStr, ":", Name], NumberedName),
+		Rval = const(string_const(NumberedName))
+	;
 		% We prefer a null pointer to a pointer to an empty string,
 		% since this way we don't need many copies of the empty string.
 		Rval = const(int_const(0))
-	;
-		Rval = const(string_const(Name))
 	),
 	MaybeRval = yes(Rval).
 
@@ -615,7 +648,7 @@
 	% 	mercury_stack_layout.h - contains macros to access these
 	%			 	constants.
 
-	% Construct a representation of a live_value_type.
+	% Construct a representation of a live_value_type without the name.
 	%
 	% Low integers for special values, a pointer for other values.
 	% (Remember to keep the low integers below the max varint value in
@@ -637,7 +670,7 @@
 	{ Rval = const(int_const(4)) }.
 stack_layout__represent_live_value_type(unwanted, Rval) -->
 	{ Rval = const(int_const(5)) }.
-stack_layout__represent_live_value_type(var(Type, _Inst), Rval) -->
+stack_layout__represent_live_value_type(var(_, _, Type, _Inst), Rval) -->
 	stack_layout__get_cell_number(CNum0),
 	{ base_type_layout__construct_pseudo_type_info(Type, Rval0,
 		CNum0, CNum1) },
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.10
diff -u -u -r1.10 trace.m
--- trace.m	1998/06/18 06:06:58	1.10
+++ trace.m	1998/07/06 09:00:43
@@ -101,6 +101,9 @@
 
 :- pred trace__path_to_string(goal_path::in, string::out) is det.
 
+	% Extract the lval of the stack slot that holds the event number.
+:- pred trace__get_event_num_slot(trace_info::in, lval::out) is det.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -140,6 +143,7 @@
 	% of a procedure.
 :- type trace_info
 	--->	trace_info(
+			lval,	% stack slot of event number
 			lval,	% stack slot of call sequence number
 			lval,	% stack slot of call depth
 			trace_type
@@ -160,6 +164,7 @@
 	).
 
 trace__setup(TraceLevel) -->
+	code_info__get_trace_slot(EventNumSlot),
 	code_info__get_trace_slot(CallNumSlot),
 	code_info__get_trace_slot(CallDepthSlot),
 	( { trace_level_trace_ports(TraceLevel, yes) } ->
@@ -168,11 +173,14 @@
 		code_info__get_trace_slot(CallFromFullSlot),
 		{ TraceType = interface_trace(CallFromFullSlot) }
 	),
-	{ TraceInfo = trace_info(CallNumSlot, CallDepthSlot, TraceType) },
+	{ TraceInfo = trace_info(EventNumSlot, CallNumSlot, CallDepthSlot,
+				TraceType) },
 	code_info__set_maybe_trace_info(yes(TraceInfo)).
 
 trace__generate_slot_fill_code(TraceInfo, TraceCode) :-
-	TraceInfo = trace_info(CallNumLval, CallDepthLval, TraceType),
+	TraceInfo = trace_info(EventNumLval, CallNumLval, CallDepthLval,
+		TraceType),
+	trace__stackref_to_string(EventNumLval, EventNumStr),
 	trace__stackref_to_string(CallNumLval, CallNumStr),
 	trace__stackref_to_string(CallDepthLval, CallDepthStr),
 	(
@@ -189,6 +197,7 @@
 	;
 		TraceType = full_trace,
 		string__append_list([
+			"\t\t", EventNumStr, " = MR_trace_event_number;\n",
 			"\t\t", CallNumStr, " = MR_trace_incr_seq();\n",
 			"\t\t", CallDepthStr, " = MR_trace_incr_depth();"
 		], TraceStmt)
@@ -199,7 +208,7 @@
 	]).
 
 trace__prepare_for_call(TraceInfo, TraceCode) :-
-	TraceInfo = trace_info(_CallNumLval, CallDepthLval, TraceType),
+	TraceInfo = trace_info(_, _, CallDepthLval, TraceType),
 	trace__stackref_to_string(CallDepthLval, CallDepthStr),
 	string__append_list(["MR_trace_reset_depth(", CallDepthStr, ");\n"],
 		ResetDepthStmt),
@@ -221,7 +230,7 @@
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
 	(
 		{ MaybeTraceInfo = yes(TraceInfo) },
-		{ TraceInfo = trace_info(_, _, full_trace) }
+		{ TraceInfo = trace_info(_, _, _, full_trace) }
 	->
 		{ Goal = _ - GoalInfo },
 		{ goal_info_get_goal_path(GoalInfo, Path) },
@@ -256,7 +265,7 @@
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
 	(
 		{ MaybeTraceInfo = yes(TraceInfo) },
-		{ TraceInfo = trace_info(_, _, full_trace) }
+		{ TraceInfo = trace_info(_, _, _, full_trace) }
 	->
 		{ trace__convert_nondet_pragma_port_type(PragmaPort, Port) },
 		trace__generate_event_code(Port, nondet_pragma, TraceInfo,
@@ -310,7 +319,7 @@
 	set__list_to_set(TvarDataList, TvarDataSet),
 	LayoutLabelInfo = layout_label_info(VarInfoSet, TvarDataSet),
 	llds_out__get_label(Label, yes, LabelStr),
-	TraceInfo = trace_info(CallNumLval, CallDepthLval, TraceType),
+	TraceInfo = trace_info(_, CallNumLval, CallDepthLval, TraceType),
 	trace__stackref_to_string(CallNumLval, CallNumStr),
 	trace__stackref_to_string(CallDepthLval, CallDepthStr),
 	Quote = """",
@@ -324,7 +333,7 @@
 		trace__stackref_to_string(CallFromFullLval, FlagStr)
 	),
 	SaveStmt = "\t\tsave_transient_registers();\n",
-	RestoreStmt = "\t\trestore_transient_registers();",
+	RestoreStmt = "\t\trestore_transient_registers();\n",
 	string__int_to_string(MaxReg, MaxRegStr),
 	string__append_list([
 		"\t\tMR_trace((const MR_Stack_Layout_Label *)\n",
@@ -335,7 +344,9 @@
 		"\t\t\t", Quote, PathStr, Quote, Comma,
 		MaxRegStr, Comma, FlagStr, ");\n"],
 		CallStmt),
-	string__append_list([SaveStmt, CallStmt, RestoreStmt], TraceStmt),
+	GotoStmt = "\t\tif (MR_trace_goto != NULL) GOTO(MR_trace_goto);",
+	string__append_list([SaveStmt, CallStmt, RestoreStmt, GotoStmt],
+		TraceStmt),
 	TraceCode =
 		node([
 			label(Label)
@@ -376,8 +387,8 @@
 	),
 	varset__lookup_name(VarSet, Var, "V_", Name),
 	instmap__lookup_var(InstMap, Var, Inst),
-	LiveType = var(Type, Inst),
-	VarInfo = var_info(Lval, LiveType, Name),
+	LiveType = var(Var, Name, Type, Inst),
+	VarInfo = var_info(Lval, LiveType),
 	type_util__vars(Type, TypeVars),
 	set__insert_list(Tvars0, TypeVars, Tvars1)
 	},
@@ -508,3 +519,7 @@
 	nondet_pragma_first).
 trace__convert_nondet_pragma_port_type(nondet_pragma_later,
 	nondet_pragma_later).
+
+%-----------------------------------------------------------------------------%
+
+trace__get_event_num_slot(trace_info(EventNumSlot, _, _, _), EventNumSlot).
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/Togl-1.2
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.31
diff -u -u -r1.31 Mmakefile
--- Mmakefile	1998/07/03 02:35:04	1.31
+++ Mmakefile	1998/07/06 06:45:30
@@ -14,7 +14,7 @@
 #-----------------------------------------------------------------------------#
 
 CFLAGS		= -I$(MERCURY_DIR)/runtime -I$(MERCURY_DIR)/boehm_gc -g \
-		  $(DLL_CFLAGS) $(EXTRA_CFLAGS)
+		  $(DLL_CFLAGS) $(EXTRA_CFLAGS) -DMR_LOWLEVEL_DEBUG
 MGNUC		= MERCURY_C_INCL_DIR=. $(SCRIPTS_DIR)/mgnuc
 MGNUCFLAGS	= --no-ansi $(EXTRA_MGNUCFLAGS) $(CFLAGS)
 MOD2C		= $(SCRIPTS_DIR)/mod2c
@@ -70,6 +70,8 @@
 			mercury_trace_base.h	\
 			mercury_trace_external.h \
 			mercury_trace_internal.h \
+			mercury_trace_spy.h	\
+			mercury_trace_tables.h	\
 			mercury_trace_util.h	\
 			mercury_trail.h		\
 			mercury_types.h		\
@@ -122,6 +124,8 @@
 			mercury_trace_base.c	\
 			mercury_trace_external.c \
 			mercury_trace_internal.c \
+			mercury_trace_spy.c	\
+			mercury_trace_tables.c	\
 			mercury_trace_util.c	\
 			mercury_trail.c 	\
 			mercury_type_info.c	\
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.6
diff -u -u -r1.6 mercury_engine.h
--- mercury_engine.h	1998/06/18 04:30:43	1.6
+++ mercury_engine.h	1998/07/06 07:04:36
@@ -243,6 +243,8 @@
 
 #endif	/* !MR_THREAD_SAFE */
 
+#define	MR_CONTEXT(x)		MR_ENGINE(context).x
+
 #ifndef CONSERVATIVE_GC
   #define IF_NOT_CONSERVATIVE_GC(x)	x
 #else
Index: runtime/mercury_label.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_label.c,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_label.c
--- mercury_label.c	1998/07/03 02:35:13	1.7
+++ mercury_label.c	1998/07/03 11:45:12
@@ -153,6 +153,8 @@
 	int	mid;
 	int	i;
 
+	MR_do_init_label_tables();
+
 	if (!entry_array_sorted) {
 		qsort(entry_array, entry_array_next, sizeof(MR_Entry),
 			compare_entry_addr);
@@ -244,5 +246,6 @@
 void
 MR_process_all_internal_labels(void f(const void *))
 {
+	MR_do_init_label_tables();
 	process_all_entries(internal_addr_table, f);
 }
Index: runtime/mercury_memory.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.c,v
retrieving revision 1.11
diff -u -u -r1.11 mercury_memory.c
--- mercury_memory.c	1998/06/18 04:30:44	1.11
+++ mercury_memory.c	1998/07/03 12:07:22
@@ -243,16 +243,16 @@
 {
 #ifdef CONSERVATIVE_GC
 	GC_FREE(ptr);
-
 #else
 	free(ptr);
 #endif
 }
+
+/*
+** Note: checked_malloc()ed structures never contain pointers into GCed memory,
+** so we don't need to GC_malloc() them. (cf. newmem())
+*/
 
-		/* Note: checked_malloc()ed structures */
-		/* never contain pointers into GCed    */
-		/* memory, so we don't need to         */
-		/* GC_malloc() them. (cf. newmem())    */
 void *
 checked_malloc(size_t n)
 {
@@ -266,7 +266,6 @@
 	return p;
 }
 
-
 void *
 checked_realloc(void *old, size_t n)
 {
@@ -279,4 +278,3 @@
 
 	return p;
 }
-
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.c,v
retrieving revision 1.8
diff -u -u -r1.8 mercury_misc.c
--- mercury_misc.c	1998/07/03 02:35:17	1.8
+++ mercury_misc.c	1998/07/06 07:06:01
@@ -233,9 +233,9 @@
 	for(i=1; i<=8; i++) {
 		x = (Integer) get_reg(i);
 #ifndef CONSERVATIVE_GC
-		if ( (Integer) heap_zone->min <= x
-				&& x < (Integer) heap_zone->top) {
-			x -= (Integer) heap_zone->min;
+		if ((Integer) MR_ENGINE(heap_zone)->min <= x
+				&& x < (Integer) MR_ENGINE(heap_zone)->top) {
+			x -= (Integer) MR_ENGINE(heap_zone)->min;
 		}
 #endif
 		printf("%8lx ", (long) x);
@@ -274,7 +274,8 @@
 {
 #ifndef CONSERVATIVE_GC
 	printf("ptr 0x%p, offset %3ld words\n",
-		(const void *) h, (long) (Integer) (h - heap_zone->min));
+		(const void *) h,
+		(long) (Integer) (h - MR_ENGINE(heap_zone)->min));
 #else
 	printf("ptr 0x%p\n",
 		(const void *) h);
@@ -286,7 +287,8 @@
 printdetstack(const Word *s)
 {
 	printf("ptr 0x%p, offset %3ld words\n",
-		(const void *) s, (long) (Integer) (s - detstack_zone->min));
+		(const void *) s,
+		(long) (Integer) (s - MR_CONTEXT(detstack_zone)->min));
 	return;
 }
 
@@ -295,12 +297,14 @@
 {
 #ifndef	MR_DEBUG_NONDET_STACK
 	printf("ptr 0x%p, offset %3ld words\n",
-		(const void *) s, (long) (Integer) (s - nondetstack_zone->min));
+		(const void *) s,
+		(long) (Integer) (s - MR_CONTEXT(nondetstack_zone)->min));
 #else
-	if (s > nondetstack_zone->min) {
+	if (s > MR_CONTEXT(nondetstack_zone)->min) {
 		printf("ptr 0x%p, offset %3ld words, procedure %s\n",
 			(const void *) s, 
-			(long) (Integer) (s - nondetstack_zone->min),
+			(long) (Integer)
+				(s - MR_CONTEXT(nondetstack_zone)->min),
 			(const char *) s[PREDNM]);
 	} else {
 		/*
@@ -309,7 +313,8 @@
 		*/
 		printf("ptr 0x%p, offset %3ld words\n",
 			(const void *) s, 
-			(long) (Integer) (s - nondetstack_zone->min));
+			(long) (Integer)
+				(s - MR_CONTEXT(nondetstack_zone)->min));
 	}
 #endif
 	return;
@@ -322,7 +327,7 @@
 
 	printf("frame at ptr 0x%p, offset %3ld words\n",
 		(const void *) fr, 
-		(long) (Integer) (fr - nondetstack_zone->min));
+		(long) (Integer) (fr - MR_CONTEXT(nondetstack_zone)->min));
 #ifdef	MR_DEBUG_NONDET_STACK
 	printf("\t predname  %s\n", bt_prednm(fr));
 #endif
@@ -345,7 +350,8 @@
 	reg	Word	*fr;
 
 	printf("\nnondstack dump\n");
-	for (fr = maxfr; fr > nondetstack_zone->min; fr = bt_prevfr(fr)) {
+	for (fr = maxfr; fr > MR_CONTEXT(nondetstack_zone)->min;
+			fr = bt_prevfr(fr)) {
 		dumpframe(fr);
 	}
 	return;
@@ -390,8 +396,8 @@
 		value = (Integer) get_reg(i+1);
 
 #ifndef	CONSERVATIVE_GC
-		if ((Integer) heap_zone->min <= value
-				&& value < (Integer) heap_zone->top) {
+		if ((Integer) MR_ENGINE(heap_zone)->min <= value &&
+				value < (Integer) MR_ENGINE(heap_zone)->top) {
 			printf("(heap) ");
 		}
 #endif
@@ -467,9 +473,11 @@
 	return p;
 }
 
-/* XXX will need to modify this to kill other threads if MR_THREAD_SAFE
- * (and cleanup resources, etc....)
- */
+/*
+** XXX will need to modify this to kill other threads if MR_THREAD_SAFE
+** (and cleanup resources, etc....)
+*/
+
 void 
 fatal_error(const char *message) {
 	fprintf(stderr, "Mercury runtime: %s\n", message);
@@ -499,4 +507,3 @@
 {
 	HASH_STRING_FUNC_BODY
 }
-
Index: runtime/mercury_overflow.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_overflow.h,v
retrieving revision 1.3
diff -u -u -r1.3 mercury_overflow.h
--- mercury_overflow.h	1998/03/16 12:23:35	1.3
+++ mercury_overflow.h	1998/07/06 07:13:23
@@ -24,54 +24,54 @@
 #include "mercury_regs.h"
 #include "mercury_misc.h"	/* for fatal_error() */
 
-#define	heap_overflow_check()					\
-			(					\
-				IF (MR_hp >= heap_zone->top,(	\
-					fatal_error("heap overflow") \
-				)),				\
-				IF (MR_hp > heap_zone->max,(	\
-					heap_zone->max = MR_hp	\
-				)),				\
-				(void)0				\
-			)
+#define	heap_overflow_check()						\
+		(							\
+			IF (MR_hp >= MR_ENGINE(heap_zone)->top,(	\
+				fatal_error("heap overflow")		\
+			)),						\
+			IF (MR_hp > MR_ENGINE(heap_zone)->max,(		\
+				MR_ENGINE(heap_zone)->max = MR_hp	\
+			)),						\
+			(void)0						\
+		)
 
-#define	detstack_overflow_check()				\
-			(					\
-				IF (MR_sp >= detstack_zone->top,(	\
-					fatal_error("stack overflow") \
-				)),				\
-				IF (MR_sp > detstack_zone->max,(	\
-					detstack_zone->max = MR_sp	\
-				)),				\
-				(void)0				\
-			)
+#define	detstack_overflow_check()					\
+		(							\
+			IF (MR_sp >= MR_CONTEXT(detstack_zone)->top,(	\
+				fatal_error("stack overflow")		\
+			)),						\
+			IF (MR_sp > MR_CONTEXT(detstack_zone)->max,(	\
+				MR_CONTEXT(detstack_zone)->max = MR_sp	\
+			)),						\
+			(void)0						\
+		)
 
-#define	detstack_underflow_check()				\
-			(					\
-				IF (MR_sp < detstack_zone->min,(		\
-					fatal_error("stack underflow") \
-				)),				\
-				(void)0				\
-			)
+#define	detstack_underflow_check()					\
+		(							\
+			IF (MR_sp < MR_CONTEXT(detstack_zone)->min,(	\
+				fatal_error("stack underflow")		\
+			)),						\
+			(void)0						\
+		)
 
-#define	nondstack_overflow_check()				\
-			(					\
-				IF (MR_maxfr >= nondetstack_zone->top,(	\
-					fatal_error("nondetstack overflow") \
-				)),				\
-				IF (MR_maxfr > nondetstack_zone->max,(	\
-					nondetstack_zone->max = MR_maxfr	\
-				)),				\
-				(void)0				\
-			)
+#define	nondstack_overflow_check()					\
+		(							\
+			IF (MR_maxfr >= MR_CONTEXT(nondetstack_zone)->top,( \
+				fatal_error("nondetstack overflow")	\
+			)),						\
+			IF (MR_maxfr > MR_CONTEXT(nondetstack_zone)->max,( \
+				MR_CONTEXT(nondetstack_zone)->max = MR_maxfr \
+			)),						\
+			(void)0						\
+		)
 
-#define	nondstack_underflow_check()				\
-			(					\
-				IF (MR_maxfr < nondetstack_zone->min,(	\
-					fatal_error("nondetstack underflow") \
-				)),				\
-				(void)0				\
-			)
+#define	nondstack_underflow_check()					\
+		(							\
+			IF (MR_maxfr < MR_CONTEXT(nondetstack_zone)->min,( \
+				fatal_error("nondetstack underflow")	\
+			)),						\
+			(void)0						\
+		)
 
 #endif /* MR_CHECK_FOR_OVERFLOW */
 
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_stack_layout.h
--- mercury_stack_layout.h	1998/06/18 06:08:03	1.7
+++ mercury_stack_layout.h	1998/07/06 09:15:44
@@ -275,12 +275,18 @@
 				*/
 } MR_Stack_Layout_Vars;
 
-#define	MR_name_if_present(vars, i)					\
-				((vars->MR_slvs_names != NULL		\
-				&& vars->MR_slvs_names[(i)] != NULL)	\
-				? vars->MR_slvs_names[(i)]		\
+#define	MR_name_if_present(vars, i)					    \
+				((vars->MR_slvs_names != NULL		    \
+				&& vars->MR_slvs_names[(i)] != NULL)	    \
+				? strchr(vars->MR_slvs_names[(i)], ':') + 1 \
 				: "")
 
+#define	MR_full_name_if_present(vars, i)				    \
+				((vars->MR_slvs_names != NULL		    \
+				&& vars->MR_slvs_names[(i)] != NULL)	    \
+				? vars->MR_slvs_names[(i)]		    \
+				: "")
+
 typedef	struct MR_Stack_Layout_Entry_Struct {
 	Code			*MR_sle_code_addr;
 	MR_Determinism		MR_sle_detism;
@@ -296,6 +302,7 @@
 	/* the fields from here onwards are present only with trace layouts */
 	struct MR_Stack_Layout_Label_Struct
 				*MR_sle_call_label;
+	int			MR_sle_event_slot;
 } MR_Stack_Layout_Entry;
 
 typedef	struct MR_Stack_Layout_Label_Struct {
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.11
diff -u -u -r1.11 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/07/03 02:35:23	1.11
+++ mercury_stack_trace.c	1998/07/06 07:31:55
@@ -182,7 +182,8 @@
 			return STEP_ERROR_AFTER;
 		}
 
-		success = (Code *) field(0, *stack_trace_sp_ptr, -number);
+		success = (Code *) based_detstackvar(*stack_trace_sp_ptr,
+					number);
 		*stack_trace_sp_ptr = *stack_trace_sp_ptr -
 			entry_layout->MR_sle_stack_slots;
 	} else {
@@ -254,15 +255,42 @@
 	fprintf(fp, "%9d ", start_level);
 
 	if (count > 1) {
-		fprintf(fp, " %3d*", count);
+		fprintf(fp, " %3d* ", count);
 	} else {
-		fprintf(fp, "%5s", "");
+		fprintf(fp, "%5s ", "");
 	}
 
-	fprintf(fp, " %s:%s/%ld-%ld (%s)\n",
+	MR_print_proc_id(fp, entry_layout, NULL);
+}
+
+void
+MR_print_proc_id_to_stdout(const MR_Stack_Layout_Entry *entry_layout)
+{
+	MR_print_proc_id(stdout, entry_layout, NULL);
+}
+
+void
+MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
+	const char *extra)
+{
+	/*
+	** The following should be a full identification of the procedure
+	** provided (a) there was no intermodule optimization and (b) we are
+	** not interested in the details of compiler-generated procedures.
+	*/
+
+	fprintf(fp, "%s %s:%s/%ld-%ld (%s)",
+		entry_layout->MR_sle_pred_or_func == MR_PREDICATE ?
+			"pred" : "func",
 		entry_layout->MR_sle_def_module,
 		entry_layout->MR_sle_name,
 		(long) entry_layout->MR_sle_arity,
 		(long) entry_layout->MR_sle_mode,
 		detism_names[entry_layout->MR_sle_detism]);
+
+	if (extra != NULL) {
+		printf(" %s\n", extra);
+	} else {
+		printf("\n");
+	}
 }
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_stack_trace.h
--- mercury_stack_trace.h	1998/07/03 02:35:25	1.7
+++ mercury_stack_trace.h	1998/07/06 07:27:46
@@ -68,4 +68,15 @@
 
 Code	*MR_stack_trace_bottom;
 
+/*
+** 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.
+*/
+
+extern	void	MR_print_proc_id_to_stdout(const MR_Stack_Layout_Entry *entry);
+extern	void	MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
+			const char *extra);
+
 #endif /* MERCURY_STACK_TRACE_H */
Index: runtime/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.c,v
retrieving revision 1.14
diff -u -u -r1.14 mercury_trace.c
--- mercury_trace.c	1998/07/03 02:35:33	1.14
+++ mercury_trace.c	1998/07/06 10:01:00
@@ -25,21 +25,28 @@
 #include "mercury_trace_util.h"
 #include "mercury_trace_internal.h"
 #include "mercury_trace_external.h"
+#include "mercury_trace_spy.h"
+#include "mercury_memory.h"
 #include "mercury_engine.h"
 #include "mercury_wrapper.h"
 #include "mercury_misc.h"
 #include <stdio.h>
 #include <unistd.h>		/* for the write system call */
 
-static	MR_trace_cmd_info	MR_trace_ctrl = { MR_CMD_GOTO, 0, 0, FALSE };
+Code				*MR_trace_goto = NULL;
+int				MR_trace_goto_reg_count = 0;
 
-static	void	MR_trace_event(MR_trace_cmd_info *cmd,
+static	MR_Trace_Cmd_Info	MR_trace_ctrl = { MR_CMD_GOTO, 0, 0,
+					MR_PRINT_LEVEL_SOME, FALSE };
+
+static	void	MR_trace_event(MR_Trace_Cmd_Info *cmd,
 			const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
+			MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 			const char *path, int max_r_num);
 
-static	void	MR_trace_event_report(const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
+static	void	MR_trace_event_report(MR_Trace_Cmd_Info *cmd,
+			const MR_Stack_Layout_Label *layout,
+			MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 			const char *path, int max_r_num);
 
 /*
@@ -48,73 +55,139 @@
 */
 
 void
-MR_trace(const MR_Stack_Layout_Label *layout, MR_trace_port port,
+MR_trace(const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
 	Unsigned seqno, Unsigned depth, const char *path, int max_r_num,
 	bool trace_this)
 {
+	MR_Spy_Action	action;
+	bool		match;
+
 	if (! (MR_trace_enabled && trace_this))
 		return;
 
 	MR_trace_event_number++;
 
+#ifdef	MR_TRACE_HISTOGRAM
+
+	if (depth >= MR_trace_histogram_max) {
+		if (MR_trace_histogram_max == 0) {
+			MR_trace_histogram_max = MR_INIT_HISTOGRAM_SIZE;
+			MR_trace_histogram_all = checked_malloc(
+							MR_trace_histogram_max
+							* sizeof(int));
+			MR_trace_histogram_exp = checked_malloc(
+							MR_trace_histogram_max
+							* sizeof(int));
+		} else {
+			MR_trace_histogram_max *= 2;
+			MR_trace_histogram_all = checked_realloc(
+							MR_trace_histogram_all,
+							MR_trace_histogram_max
+							* sizeof(int));
+			MR_trace_histogram_exp = checked_realloc(
+							MR_trace_histogram_exp,
+							MR_trace_histogram_max
+							* sizeof(int));
+		}
+	}
+
+	if (depth > MR_trace_histogram_hwm) {
+		MR_trace_histogram_hwm = depth;
+	}
+
+	MR_trace_histogram_all[depth]++;
+	MR_trace_histogram_exp[depth]++;
+
+#endif	/* MR_TRACE_HISTOGRAM */
+
 	switch (MR_trace_ctrl.MR_trace_cmd) {
 		case MR_CMD_FINISH:
 			if (MR_trace_ctrl.MR_trace_stop_seqno == seqno
-			&& MR_port_is_final(port)) {
+					&& MR_port_is_final(port)) {
 				MR_trace_event(&MR_trace_ctrl, layout,
-					port, seqno, depth, path, max_r_num);
-
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
 					port, seqno, depth, path, max_r_num);
+				return;
+			} else {
+				goto check_stop_print;
 			}
 
-			break;
-
 		case MR_CMD_GOTO:
 			if (MR_trace_event_number >=
-				MR_trace_ctrl.MR_trace_stop_event
-			|| MR_event_matches_spy_point(layout)) {
+					MR_trace_ctrl.MR_trace_stop_event) {
 				MR_trace_event(&MR_trace_ctrl, layout,
-					port, seqno, depth, path, max_r_num);
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
 					port, seqno, depth, path, max_r_num);
+				return;
+			} else {
+				goto check_stop_print;
 			}
 
-			break;
-
 		case MR_CMD_RESUME_FORWARD:
 			if (MR_port_is_final(port)) {
 				MR_trace_event(&MR_trace_ctrl, layout,
 					port, seqno, depth, path, max_r_num);
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
-					port, seqno, depth, path, max_r_num);
+				return;
+			} else {
+				goto check_stop_print;
 			}
 
-			break;
-
 		case MR_CMD_TO_END:
-			if (MR_event_matches_spy_point(layout)) {
-				MR_trace_event(&MR_trace_ctrl, layout,
-					port, seqno, depth, path, max_r_num);
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
+			goto check_stop_print;
+
+		default:
+			fatal_error("invalid cmd in MR_trace");
+			return;
+	}
+
+check_stop_print:
+
+	if (MR_trace_ctrl.MR_trace_must_check) {
+		/*
+		** The value of MR_trace_ctrl.MR_trace_must_check was
+		** precomputed when the command was set up; it was set to TRUE
+		** iff either MR_trace_ctrl.MR_trace_strict is FALSE (allowing
+		** us to stop at breakpoints whose action is MR_SPY_STOP) or
+		** MR_trace_ctrl.MR_trace_print_level is something other than
+		** MR_PRINT_LEVEL_NONE (allowing us to print at least some
+		** events). The precomputation avoids several jumps in the
+		** very frequent case that MR_trace_must_check is false.
+		*/
+
+		match = MR_event_matches_spy_point(layout, port, &action);
+		if (! match) {
+			if (MR_trace_ctrl.MR_trace_print_level ==
+					MR_PRINT_LEVEL_ALL) {
+				MR_trace_event_report(&MR_trace_ctrl, layout,
 					port, seqno, depth, path, max_r_num);
 			}
 
-			break;
+			return;
+		}
 
-		default:
-			fatal_error("invalid cmd in MR_trace");
-			break;
+		if ((! MR_trace_ctrl.MR_trace_strict)
+				&& action == MR_SPY_STOP) {
+			MR_trace_event(&MR_trace_ctrl, layout, port,
+				seqno, depth, path, max_r_num);
+			return;
+		}
+
+		if (MR_trace_ctrl.MR_trace_print_level != MR_PRINT_LEVEL_NONE) {
+			/*
+			** It doesn't matter whether action is MR_SPY_STOP or
+			** MR_SPY_PRINT; even if it is MR_SPY_STOP, we want
+			** to print it if printing is allowed and we did not
+			** stop.
+			*/
+
+			MR_trace_event_report(&MR_trace_ctrl, layout, port,
+				seqno, depth, path, max_r_num);
+			return;
+		}
 	}
 }
 
 static void
-MR_trace_event(MR_trace_cmd_info *cmd,
-	const MR_Stack_Layout_Label *layout, MR_trace_port port,
+MR_trace_event(MR_Trace_Cmd_Info *cmd,
+	const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
 	Unsigned seqno, Unsigned depth, const char *path, int max_r_num)
 {
 	int	max_mr_num;
@@ -126,6 +199,10 @@
 	}
 
 	MR_copy_regs_to_saved_regs(max_mr_num);
+
+	MR_trace_goto = NULL;
+	MR_trace_goto_reg_count = max_mr_num;
+
 #ifdef MR_USE_EXTERNAL_DEBUGGER
 	if (MR_trace_debugger == MR_TRACE_EXTERNAL) {
 		MR_trace_event_external(layout, port, seqno, depth, path);
@@ -140,18 +217,19 @@
 
 	MR_trace_event_internal(cmd, layout, port, seqno, depth, path);
 #endif
-	MR_copy_saved_regs_to_regs(max_mr_num);
+	MR_copy_saved_regs_to_regs(MR_trace_goto_reg_count);
 }
 
 static void
-MR_trace_event_report(const MR_Stack_Layout_Label *layout, MR_trace_port port,
+MR_trace_event_report(MR_Trace_Cmd_Info *cmd,
+	const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
 	Unsigned seqno, Unsigned depth, const char *path, int max_r_num)
 {
 #ifdef MR_USE_EXTERNAL_DEBUGGER
 	if (MR_trace_debugger == MR_TRACE_EXTERNAL) {
 		fatal_abort("trying to report an event to external debugger");
 	} else {
-		MR_trace_event_internal_report(layout,
+		MR_trace_event_internal_report(cmd, layout,
 			port, seqno, depth, path);
 	}
 #else
@@ -160,6 +238,6 @@
 	** This is enforced by mercury_wrapper.c.
 	*/
 
-	MR_trace_event_internal_report(layout, port, seqno, depth, path);
+	MR_trace_event_internal_report(cmd, layout, port, seqno, depth, path);
 #endif
 }
Index: runtime/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_trace.h
--- mercury_trace.h	1998/07/03 02:35:38	1.9
+++ mercury_trace.h	1998/07/05 05:56:24
@@ -50,17 +50,20 @@
 	MR_PORT_SWITCH,
 	MR_PORT_PRAGMA_FIRST,
 	MR_PORT_PRAGMA_LATER
-} MR_trace_port;
+} MR_Trace_Port;
 
 extern	void	MR_trace(
 	const MR_Stack_Layout_Label *,	/* layout info for the event */
-	MR_trace_port,
+	MR_Trace_Port,
 	Word,			/* call sequence number */
 	Word,			/* call depth */
 	const char *,		/* path to event goal within procedure */
 	int,			/* highest numbered rN register in use */
 	bool);			/* is this event supposed to be traced */
 
+extern	Code	*MR_trace_goto;
+extern	int	MR_trace_goto_reg_count;
+
 /* The interface between the debuggers and the tracing subsystem. */
 
 /*
@@ -89,15 +92,36 @@
 	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;
+} MR_Trace_Cmd_Type;
+
+typedef enum {
+	MR_PRINT_LEVEL_NONE,	/* no events at all                        */
+	MR_PRINT_LEVEL_SOME,	/* events matching an active spy point     */
+	MR_PRINT_LEVEL_ALL	/* all events                              */
+} MR_Trace_Print_Level;
 
 typedef struct {
-	MR_trace_cmd_type	MR_trace_cmd;	
-	Unsigned		MR_trace_stop_seqno;
-	Unsigned		MR_trace_stop_event;
-	bool			MR_trace_print_intermediate;
-} MR_trace_cmd_info;
+	MR_Trace_Cmd_Type	MR_trace_cmd;	
+	Unsigned		MR_trace_stop_seqno;	/* if MR_CMD_FINISH */
+	Unsigned		MR_trace_stop_event;	/* if MR_CMD_GOTO   */
+	MR_Trace_Print_Level	MR_trace_print_level;
+	bool			MR_trace_strict;
+
+				/*
+				** The next field is an optimization;
+				** it must be set to !MR_trace_strict ||
+				** MR_trace_print_level != MR_PRINT_LEVEL_NONE
+				*/
+	bool			MR_trace_must_check;
+} MR_Trace_Cmd_Info;
+
+#define	MR_port_is_final(port)		((port) == MR_PORT_EXIT || \
+					(port) == MR_PORT_FAIL)
+
+#define	MR_port_is_interface(port)	((port) == MR_PORT_CALL || \
+					(port) == MR_PORT_EXIT || \
+					(port) == MR_PORT_FAIL)
 
-#define	MR_port_is_final(port)	(port == MR_PORT_EXIT || port == MR_PORT_FAIL)
+#define	MR_port_is_entry(port)		((port) == MR_PORT_CALL)
 
 #endif /* MERCURY_TRACE_H */
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_base.c
--- mercury_trace_base.c	1998/07/03 05:34:46	1.1
+++ mercury_trace_base.c	1998/07/05 04:27:33
@@ -89,6 +89,15 @@
 
 Bool		MR_trace_from_full = 1;
 
+#ifdef	MR_TRACE_HISTOGRAM
+
+int		*MR_trace_histogram_all = NULL;
+int		*MR_trace_histogram_exp = NULL;
+int		MR_trace_histogram_max  = 0;
+int		MR_trace_histogram_hwm  = 0;
+
+#endif	/* MR_TRACE_HISTOGRAM */
+
 void
 MR_trace_init(void)
 {
@@ -134,6 +143,11 @@
 
 		fprintf(fp, "Last trace event was event #%ld.\n",
 			(long) MR_trace_event_number);
+
+#ifdef	MR_TRACE_HISTOGRAM
+		MR_trace_print_histogram(fp, "All-inclusive",
+			MR_trace_histogram_all, MR_trace_histogram_hwm);
+#endif	/* MR_TRACE_HISTOGRAM */
 	}
 }
 
@@ -153,3 +167,22 @@
 		write(fd, buf, strlen(buf));
 	}
 }
+
+#ifdef	MR_TRACE_HISTOGRAM
+void
+MR_trace_print_histogram(FILE *fp, const char *which, int *histogram, int max)
+{
+	int	i;
+
+	fprintf(fp, "%s histogram\n", which);
+	for (i = 1; i <= max; i++) {
+		fprintf(fp, "depth %4d: %10d", i, histogram[i]);
+		if (i + 1 <= max && histogram[i] != 0) {
+			fprintf(fp, ", branching factor %7.2f\n",
+				(float) histogram[i+1] / (float) histogram[i]);
+		} else {
+			fprintf(fp, "\n");
+		}
+	}
+}
+#endif	/* MR_TRACE_HISTOGRAM */
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_base.h
--- mercury_trace_base.h	1998/07/03 05:34:47	1.1
+++ mercury_trace_base.h	1998/07/05 04:02:53
@@ -71,4 +71,16 @@
 extern	void	MR_trace_report(FILE *fp);
 extern	void	MR_trace_report_raw(int fd);
 
+#ifdef	MR_TRACE_HISTOGRAM
+#define	MR_INIT_HISTOGRAM_SIZE	128
+
+extern	int	*MR_trace_histogram_all;
+extern	int	*MR_trace_histogram_exp;
+extern	int	MR_trace_histogram_max;
+extern	int	MR_trace_histogram_hwm;
+
+extern	void	MR_trace_print_histogram(FILE *fp, const char *which,
+			int *histogram, int max);
+#endif	/* MR_TRACE_HISTOGRAM */
+
 #endif /* MERCURY_TRACE_PERMANENT_H */
Index: runtime/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_external.c,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_trace_external.c
--- mercury_trace_external.c	1998/05/26 16:33:03	1.2
+++ mercury_trace_external.c	1998/07/03 05:53:25
@@ -60,11 +60,11 @@
 			Integer *debugger_request_type_ptr);
 	
 static bool	MR_found_match(const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
+			MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 			/* XXX registers */
 			const char *path, Word search_data);
 static void	MR_output_current(const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
+			MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 			Word var_list,
 			const char *path, Word current_request);
 
@@ -304,7 +304,7 @@
 
 void
 MR_trace_event_external(const MR_Stack_Layout_Label *layout,
-	MR_trace_port port, Unsigned seqno, Unsigned depth, const char *path)
+	MR_Trace_Port port, Unsigned seqno, Unsigned depth, const char *path)
 {
 	static bool searching = FALSE;
 	static Word search_data;
@@ -368,7 +368,7 @@
 
 static void
 MR_output_current(const MR_Stack_Layout_Label *layout,
-	MR_trace_port port, Unsigned seqno, Unsigned depth,
+	MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 	Word var_list,
 	const char *path, Word current_request)
 {
@@ -403,7 +403,7 @@
 
 static bool
 MR_found_match(const MR_Stack_Layout_Label *layout,
-	MR_trace_port port, Unsigned seqno, Unsigned depth,
+	MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 	/* XXX live vars */
 	const char *path, Word search_data)
 {
Index: runtime/mercury_trace_external.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_external.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_external.h
--- mercury_trace_external.h	1998/05/16 07:28:26	1.1
+++ mercury_trace_external.h	1998/07/05 04:02:53
@@ -12,7 +12,7 @@
 extern	void	MR_trace_init_external(void);
 extern	void	MR_trace_final_external(void);
 extern	void	MR_trace_event_external(const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
+			MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 			const char *path);
 
 #endif	/* MR_USE_EXTERNAL_DEBUGGER */



More information about the developers mailing list