for review: the new debugger command set (part 1 of 5)
Zoltan Somogyi
zs at cs.mu.OZ.AU
Wed Sep 16 18:19:31 AEST 1998
Since we want full debugger functionality in the release, this diff
is for inclusion in the release. The nominated reviewers are Fergus
and Tyson, but I would also like feedback from Erwan.
Note that this change is not quite complete, in two respects. One, the new
debugging chapter in the user guide is not finished; I'd like your feedback
on what level of explanatory detail is required. Two, this change makes
functions in the runtime called by MR_trace to refer to the library.
We have tried to avoid such references so far, by putting the references
into the auto-generated *_init.c files. However, we can't do this with
the new references, because this would pull into *every* executable
library modules that are required only if some module is execution traced.
I'd appreciate suggestions for better solutions.
Estimated hours taken: 160
Move the debugger command set to the proposal previously circulated,
(including the retry command) and add some extensions, such as redo events.
As part of this change, reserve fixed stack slots for the info required
by the debugger. This allows us to reduce the number of arguments to MR_trace.
Get the compiler to number framevars starting at 1 rather than 0, to allow
them to be handled the same way as stackvars. The runtime made the
corresponding change a while ago.
doc/user_guide.texi:
Add a new section on the debugger. The description of the commands
is complete, but some of the background sections are not yet done.
Update the documentation of the tracing options.
doc/generate_mdb_doc:
A new shell script that automatically converts some of the new
sections of the user guide into the online documentation of the
debugger.
doc/mdb_categories:
The fixed initial part of the online documentation.
doc/mdbrc.in:
A debugger command script that reads in the online documentation
and then defines some standard aliases.
doc/Mmakefile:
Add rules for creating mdb_doc, the file that is the online
documentation of the debugger, and for installing it together
with mdbrc.
Mmake.common.in:
Define INSTALL_DOC_DIR for doc/Mmakefile.
configure.in:
Define the variable that scripts/mdb.in and doc/mdbrc.in use to find
the right files, and get configure to perform the substitutions.
compiler/handle_options.m:
Undo the debug => trail implication, since it does not work
in the absence of a library that supplies implementations of
the trailing functions.
compiler/globals.m:
compiler/handle_options.m:
compiler/options.m:
compiler/trace.m:
Reorganize the handling of trace levels around the new options
--trace, --trace-internal, --trace-redo, and --trace-return.
compiler/trace.m:
Remove from the call to MR_trace the parameters that are now in fixed
stack slots, since MR_trace can now look them up itself.
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 retry. (The debugger cannot execute the jump itself
because it is in the wrong C stack frame.)
When generating the set of live variables at internal ports,
the variables that are in the pre-death set of the goal into which
we are entering may not be available. However, the variables in the
pre-death set that are also in the resume vars set will be available,
so now include info about them in the layout structure for the event.
Since with tracing the non-clobbered input args are in all resume vars
sets, this ensures that these input args will be available from all
internal events.
compiler/trace.m:
compiler/code_gen.m:
Before the code that executes "succeed()", emit code to push a
a temp nondet frame whose redoip points to a label in the runtime
that calls MR_trace for a REDO event and then fails, provided
--trace-redo is set.
compiler/llds.m:
Add a new code address constant, do_trace_redo_fail, which stands
for the address in the trace system to which calls MR_trace for
the redo event and then fails.
compiler/llds.m:
compiler/code_info.m:
compiler/continuation_info.m:
compiler/stack_layout.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:
Add an extra field to the proc_layout_info. If the module is shallow
traced, this field says which stack slot holds the saved value of
MR_from_full. If it is not shallow traced, this field says that
there is no such stack slot.
compiler/code_info.m:
compiler/live_vars.m:
compiler/llds_out.m:
compiler/trace.m:
Start numbering framevars from 1 internally to the compiler;
the runtime already starts from 1. This simplifies several tasks.
compiler/code_info.m:
compiler/live_vars.m:
compiler/trace.m:
If execution tracing is enabled, reserve the first few stack slots
to hold the event number of the call event, the call number, the
call depth, the redo layout structure address (if generating redo
events) and the from_full flag at the time of call (if we are doing
shallow tracing). By allocating the first four of these to fixed stack
slots, the debugger knows where to look for them without having
to be told. It finds out the location of the fifth, if needed,
from a new slot in the proc layout structure. (It is not possible
to allocate all five to fixed stack slots without wasting stack space
in some cases.)
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/globals.m:
compiler/call_gen.m:
compiler/code_info.m:
compiler/mercury_compile.m:
Add a new pred globals__want_return_layouts, which says whether the
compiler should generate layout structures for call returns. This pred
centralizes the several previous copies of the test. One of those
copies (the one in call_gen) was faulty, leading to 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.
compiler/trace.m:
compiler/llds_out.m:
Provided we are doing redo tracing, fill in the slot that holds
the layout information for the REDO event.
compiler/*.m:
Minor changes to conform to the data structure changes above and
to handle the new code address constant.
library/io.m:
Export to C code the predicates that return identities of stdin,
stdout and stderr.
library/help.m:
A module implementing a generic hierarchical but otherwise primitive
help system. This is used for the help system of the debugger.
library/library.m:
Add the help module to the library.
library/std_util.m:
Generate useful (non-dummy) layout info about builtin_aggregate
in all circumstances, even in non-debug grades and even if std_util.m
is compiled without tracing. Unless this is done, the usefulness of
the debugger is greatly reduced in debugging code called from
solutions and other callers of builtin_aggregate.
The principle applies to all higher-order library predicates,
but this change address only those which are implemented by
hand-written C modules; builtin_aggregate happens to be the only one.
runtime/mercury_goto.h:
Besides init_entry and init_entry_sl, support init_entry_asl,
which always generates stack layout information, even if the current
settings do not call for it. This is intended for use in higher-order
predicates, which may call predicates from other modules which *were*
compiled with tracing.
runtime/mercury_engine.c:
Remove bogus layouts for do_redo and other similar labels, since they
are not needed, and initialize them in the label table as labels,
not entries, since that is what they are.
runtime/mercury_label.c:
Initialize the tables before use.
runtime/mercury_macros.h:
A new file holding macros that can be useful in more than one module
of the runtime.
runtime/mercury_memory.[ch]:
Add a new function MR_copy_string.
runtime/mercury_misc.c:
Add a new function MR_memcpy_fromhigh. It differs from MR_memcpy
only when the source and destination areas overlap.
runtime/mercury_overflow.h:
Update several obsolete zone references.
runtime/mercury_stack_layout.h:
Redefine an existing macro to strip away the initial number: prefix
from the "name" of a variable, and add a new one to access the raw
unstripped data.
Add macros for accessing the fixed stack slots holding the event
number of the call event, the call number, the call depth, and,
at a redo event, the redo layout structure address.
Support the new field in proc layouts that gives the location of the
from-full flag (if any).
Add a macro MR_DEFINE_STACK_LAYOUT_ENTRY that does what the existing
macro MR_MAKE_STACK_LAYOUT_ENTRY does, except that it always creates
a layout structure. Create similar parallels for a couple of other
similar macros.
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_stacks.h:
Delete the based_framevar and based_detstackvar macros, since their
use can lead to off-by-one errors, and the saved_framevar and
saved_detstackvar macros, since they are no longer used.
runtime/*.c
Update any references to any macros removed from mercury_stacks.h.
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,
variable-strictness commands, a more flexible finish command,
and the retry command.
Pass the command structure to MR_trace_event_report, since
the user can now forcibly terminate the scrolling of reports.
Add a C module containing the code that calls MR_trace for REDO
events.
Remove the call number and call depth arguments from MR_trace,
since this info is now in fixed stack slots in every procedure that
can call MR_trace. This should reduce the size of the executable
significantly, since there are lots of calls to MR_trace.
runtime/mercury_trace_base.[ch]:
Define the data structures for the histogram, and print the histogram
when a traced program exits if MR_TRACE_HISTOGRAM is set.
Change the MR_trace_call_{seqno,depth} to Unsigned, to increase
by a factor of 2 the length of program runs that can be handled
without sequence number overflow.
runtime/mercury_conf_param.h:
Document MR_TRACE_HISTOGRAM.
runtime/mercury_trace_internal.c:
Implement the proposed command set. Command names are now words,
and several commands now have options 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.
Supports aliases, command file sourcing etc. Implements the retry
command, using the info in the fixed stack slots.
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 a 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_alias.[ch]:
New module to manage aliases for the debugger.
runtime/mercury_trace_util.[ch]:
Add a new auxiliary function used to implement restart.
Add a lot more documentation in the header file.
Use a C function exported from io.m to print variables, instead of
lower-level code.
runtime/mercury_trace*.[ch]:
Make typedef'd names conform to the naming convention.
runtime/mercury_wrapper.h:
Stylistic fixes.
runtime/Mmakefile:
Include the new modules in the library.
scripts/mdb:
scripts/mdb.in:
Remove mdb and add mdb.in. Mdb is now created during configuration
from mdb.in, filling in the name of the file that contains the default
debugger initialization commands.
scripts/ml.in:
Repeat the library archive after the runtime archive, since we now
refer to the library from the runtime.
util/mkinit.c:
Refer to the io:print/4, not io:print/3, since with io:print/3
the debugger has no control over where the stuff being printed ends up
:-(
util/info_to_mdb.c:
A program that does most of the work involved in automatically
converting user guide sections into online documentation.
(This couldn't easily be written in sh, because sh's read
command has no notion of pushback.)
util/Mmakefile:
Add info_to_mdb to the list of targets.
tests/debugger/*.inp:
tests/debugger/*.exp:
Update the inputs and expected outputs of the debugger test cases
to use the new command set and output formats.
tools/bootcheck:
Repeat the library archive after the runtime archive, since we now
refer to the library from the runtime.
Make sure that the tests in tests/debugger are executed with an
initialization setup that is equivalent to what users will see
by default.
Zoltan.
cvs diff: Diffing .
Index: Mmake.common.in
===================================================================
RCS file: /home/mercury1/repository/mercury/Mmake.common.in,v
retrieving revision 1.28
diff -u -u -r1.28 Mmake.common.in
--- Mmake.common.in 1998/08/04 14:05:50 1.28
+++ Mmake.common.in 1998/09/15 08:53:43
@@ -59,6 +59,7 @@
INSTALL_PS_DIR = $(INSTALL_PREFIX)/lib/mercury/doc
INSTALL_MAN_DIR = $(INSTALL_PREFIX)/man
INSTALL_HTML_DIR = $(INSTALL_PREFIX)/lib/mercury/html
+INSTALL_DOC_DIR = $(INSTALL_PREFIX)/lib/mercury/doc
# Specify the Mercury compiler to use for bootstrapping
MC = @BOOTSTRAP_MC@
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.133
diff -u -u -r1.133 configure.in
--- configure.in 1998/07/01 06:07:58 1.133
+++ configure.in 1998/09/16 07:04:09
@@ -57,6 +57,8 @@
AC_SUBST(PREFIX)
AC_SUBST(NONSHARED_LIB_DIR)
AC_SUBST(LIBDIR)
+DEFAULT_MERCURY_DEBUGGER_INIT_DIR=$LIBDIR/doc
+AC_SUBST(DEFAULT_MERCURY_DEBUGGER_INIT_DIR)
#-----------------------------------------------------------------------------#
case "$host" in
mips-sgi-irix5.*)
@@ -1670,8 +1672,9 @@
AC_OUTPUT(Mmake.common scripts/Mmake.vars scripts/mmc scripts/mprof
scripts/mercury_update_interface scripts/mgnuc scripts/mint scripts/ml
scripts/mmake scripts/mnc scripts/mnl scripts/mnp scripts/c2init
-scripts/msc scripts/msl scripts/msp scripts/sicstus_conv
+scripts/mdb scripts/msc scripts/msl scripts/msp scripts/sicstus_conv
scripts/mkfifo_using_mknod bindist/bindist.build_vars
+doc/mdbrc
,
for header in $CONFIG_HEADERS ; do
if test "$header" = "runtime/mercury_conf.h"; then
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing 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.123
diff -u -u -r1.123 call_gen.m
--- call_gen.m 1998/07/20 10:00:10 1.123
+++ call_gen.m 1998/09/16 05:07:30
@@ -632,38 +632,38 @@
code_info__generate_stack_livelvals(OutArgs, AfterCallInstMap,
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__want_return_layouts(Globals, WantReturnLayout) },
+ call_gen__insert_arg_livelvals(OutputArgs, WantReturnLayout,
+ 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,
- LiveVals0, LiveVals) -->
+call_gen__insert_arg_livelvals([Var - L | As], WantReturnLayout,
+ AfterCallInstMap, LiveVals0, LiveVals) -->
code_info__get_varset(VarSet),
{ varset__lookup_name(VarSet, Var, Name) },
(
- { GC_Method = accurate }
+ { WantReturnLayout = 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, WantReturnLayout, AfterCallInstMap,
[LiveVal | LiveVals0], LiveVals).
%---------------------------------------------------------------------------%
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.55
diff -u -u -r1.55 code_gen.m
--- code_gen.m 1998/08/07 00:48:44 1.55
+++ code_gen.m 1998/08/12 09:34:12
@@ -202,7 +202,8 @@
% execution tracing.
code_info__init(VarSet, Liveness, StackSlots, SaveSuccip, Globals,
PredId, ProcId, ProcInfo, InitialInst, FollowVars,
- ModuleInfo, CellCount0, OutsideResumePoint, CodeInfo0),
+ ModuleInfo, CellCount0, OutsideResumePoint, MaybeFromFullSlot,
+ CodeInfo0),
% Generate code for the procedure.
generate_category_code(CodeModel, Goal, OutsideResumePoint,
@@ -234,7 +235,8 @@
no, EntryLabel),
continuation_info__add_proc_info(proc(PredId, ProcId),
EntryLabel, TotalSlots, Detism, MaybeSuccipSlot,
- MaybeTraceCallLabel, LayoutInfo, ContInfo0, ContInfo)
+ MaybeTraceCallLabel, MaybeFromFullSlot,
+ LayoutInfo, ContInfo0, ContInfo)
;
ContInfo = ContInfo0
),
@@ -487,7 +489,7 @@
),
code_info__get_maybe_trace_info(MaybeTraceInfo),
( { MaybeTraceInfo = yes(TraceInfo) } ->
- { trace__generate_slot_fill_code(TraceInfo, TraceFillCode) }
+ trace__generate_slot_fill_code(TraceInfo, TraceFillCode)
;
{ TraceFillCode = empty }
),
@@ -693,14 +695,21 @@
}
;
{ CodeModel = model_non },
+ { MaybeTraceInfo = yes(TraceInfo2) ->
+ trace__maybe_setup_redo_event(TraceInfo2,
+ SetupRedoCode)
+ ;
+ SetupRedoCode = empty
+ },
{ SuccessCode = node([
livevals(LiveArgs) - "",
goto(do_succeed(no))
- "Return from procedure call"
]) },
{ AllSuccessCode =
+ tree(SetupRedoCode,
tree(TraceExitCode,
- SuccessCode)
+ SuccessCode))
}
),
{ ExitCode =
@@ -878,7 +887,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.228
diff -u -u -r1.228 code_info.m
--- code_info.m 1998/08/25 05:09:41 1.228
+++ code_info.m 1998/09/16 05:07:23
@@ -64,9 +64,9 @@
% Create a new code_info structure.
:- pred code_info__init(varset, set(var), stack_slots, bool, globals,
pred_id, proc_id, proc_info, instmap, follow_vars, module_info,
- int, resume_point_info, code_info).
+ int, resume_point_info, maybe(int), code_info).
:- mode code_info__init(in, in, in, in, in, in, in, in, in, in, in, in,
- out, out) is det.
+ out, out, out) is det.
% Get the globals table.
:- pred code_info__get_globals(globals, code_info, code_info).
@@ -265,10 +265,11 @@
%---------------------------------------------------------------------------%
code_info__init(Varset, Liveness, StackSlots, SaveSuccip, Globals,
- PredId, ProcId, ProcInfo, Instmap, FollowVars,
- ModuleInfo, CellCount, ResumePoint, CodeInfo) :-
+ PredId, ProcId, ProcInfo, Instmap, FollowVars, ModuleInfo,
+ CellCount, ResumePoint, MaybeFromFullSlot, CodeInfo) :-
proc_info_headvars(ProcInfo, HeadVars),
proc_info_arg_info(ProcInfo, ArgInfos),
+ proc_info_interface_code_model(ProcInfo, CodeModel),
assoc_list__from_corresponding_lists(HeadVars, ArgInfos, Args),
arg_info__build_input_arg_list(Args, ArgList),
globals__get_options(Globals, Options),
@@ -289,15 +290,9 @@
map__init(TempsInUse),
set__init(Zombies),
map__init(LayoutMap),
- code_info__max_var_slot(StackSlots, VarSlotCount0),
- proc_info_interface_code_model(ProcInfo, CodeModel),
- (
- CodeModel = model_non
- ->
- VarSlotCount is VarSlotCount0 + 1
- ;
- VarSlotCount = VarSlotCount0
- ),
+ code_info__max_var_slot(StackSlots, VarSlotMax),
+ trace__reserved_slots(ProcInfo, Globals, FixedSlots),
+ int__max(VarSlotMax, FixedSlots, SlotMax),
CodeInfo0 = code_info(
Globals,
ModuleInfo,
@@ -305,7 +300,7 @@
ProcId,
ProcInfo,
Varset,
- VarSlotCount,
+ SlotMax,
no,
Liveness,
@@ -322,25 +317,26 @@
0,
AvailSlots
),
- globals__get_trace_level(Globals, TraceLevel),
- code_info__init_maybe_trace_info(TraceLevel, ModuleInfo, ProcInfo,
- MaybeFailVars, CodeInfo0, CodeInfo1),
+ code_info__init_maybe_trace_info(Globals, ModuleInfo, ProcInfo,
+ MaybeFailVars, MaybeFromFullSlot, CodeInfo0, CodeInfo1),
code_info__init_fail_info(CodeModel, MaybeFailVars, ResumePoint,
CodeInfo1, CodeInfo).
-:- pred code_info__init_maybe_trace_info(trace_level, module_info, proc_info,
- maybe(set(var)), code_info, code_info).
-:- mode code_info__init_maybe_trace_info(in, in, in, out, in, out) is det.
-
-code_info__init_maybe_trace_info(TraceLevel, ModuleInfo, ProcInfo,
- MaybeFailVars) -->
- ( { trace_level_trace_interface(TraceLevel, yes) } ->
- trace__setup(TraceLevel, TraceInfo),
+:- pred code_info__init_maybe_trace_info(globals, module_info, proc_info,
+ maybe(set(var)), maybe(int), code_info, code_info).
+:- mode code_info__init_maybe_trace_info(in, in, in, out, out, in, out) is det.
+
+code_info__init_maybe_trace_info(Globals, ModuleInfo, ProcInfo,
+ MaybeFailVars, MaybeFromFullSlot) -->
+ { globals__get_trace_level(Globals, TraceLevel) },
+ ( { TraceLevel \= none } ->
+ trace__setup(Globals, MaybeFromFullSlot, TraceInfo),
code_info__set_maybe_trace_info(yes(TraceInfo)),
{ trace__fail_vars(ModuleInfo, ProcInfo, FailVars) },
{ MaybeFailVars = yes(FailVars) }
;
- { MaybeFailVars = no }
+ { MaybeFailVars = no },
+ { MaybeFromFullSlot = no }
).
%---------------------------------------------------------------------------%
@@ -575,6 +571,11 @@
code_info, code_info).
:- mode code_info__get_pred_proc_arginfo(in, in, out, in, out) is det.
+ % Get the set of variables currently needed by the resume
+ % points of enclosing goals.
+:- pred code_info__current_resume_point_vars(set(var), code_info, code_info).
+:- mode code_info__current_resume_point_vars(out, in, out) is det.
+
:- pred code_info__variable_to_string(var, string, code_info, code_info).
:- mode code_info__variable_to_string(in, out, in, out) is det.
@@ -755,11 +756,6 @@
{ module_info_pred_proc_info(ModuleInfo, PredId, ProcId, _, ProcInfo) },
{ proc_info_arg_info(ProcInfo, ArgInfo) }.
-%---------------------------------------------------------------------------%
-
-:- pred code_info__current_resume_point_vars(set(var), code_info, code_info).
-:- mode code_info__current_resume_point_vars(out, in, out) is det.
-
code_info__current_resume_point_vars(ResumeVars) -->
code_info__get_fail_info(FailInfo),
{ FailInfo = fail_info(ResumePointStack, _, _, _, _) },
@@ -768,8 +764,6 @@
{ map__keys(ResumeMap, ResumeMapVarList) },
{ set__list_to_set(ResumeMapVarList, ResumeVars) }.
-%---------------------------------------------------------------------------%
-
code_info__variable_to_string(Var, Name) -->
code_info__get_varset(Varset),
{ varset__lookup_name(Varset, Var, Name) }.
@@ -3088,18 +3082,8 @@
code_info__generate_var_livelvals(VarList, LiveVals0, LiveVals1),
{ set__to_sorted_list(LiveVals1, LiveVals2) },
code_info__get_globals(Globals),
- { globals__get_gc_method(Globals, GC_Method) },
- { globals__get_trace_level(Globals, TraceLevel) },
- {
- ( GC_Method = accurate
- ; trace_level_trace_returns(TraceLevel, yes)
- )
- ->
- NeedVarInfo = yes
- ;
- NeedVarInfo = no
- },
- code_info__livevals_to_livelvals(LiveVals2, NeedVarInfo,
+ { globals__want_return_layouts(Globals, WantReturnLayout) },
+ code_info__livevals_to_livelvals(LiveVals2, WantReturnLayout,
AfterCallInstMap, LiveVals3),
code_info__get_temps_in_use(TempsSet),
{ map__to_assoc_list(TempsSet, Temps) },
@@ -3121,7 +3105,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).
@@ -3130,25 +3114,25 @@
:- mode code_info__livevals_to_livelvals(in, in, in, out, in, out) is det.
code_info__livevals_to_livelvals([], _, _, []) --> [].
-code_info__livevals_to_livelvals([Lval - Var | Ls], NeedVarInfo,
+code_info__livevals_to_livelvals([Lval - Var | Ls], WantReturnLayout,
AfterCallInstMap, [LiveLval | Lives]) -->
code_info__get_varset(VarSet),
{ varset__lookup_name(VarSet, Var, Name) },
(
- { NeedVarInfo = yes }
+ { WantReturnLayout = 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),
- { 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).
+ code_info__livevals_to_livelvals(Ls, WantReturnLayout,
+ AfterCallInstMap, Lives).
:- pred code_info__get_live_value_type(slot_contents, live_value_type).
:- mode code_info__get_live_value_type(in, out) is det.
@@ -3320,10 +3304,9 @@
code_info__stack_variable(Num, Lval) -->
code_info__get_proc_model(CodeModel),
( { CodeModel = model_non } ->
- { Num1 is Num - 1 }, % framevars start at zero
- { Lval = framevar(Num1) }
+ { Lval = framevar(Num) }
;
- { Lval = stackvar(Num) } % stackvars start at one
+ { Lval = stackvar(Num) }
).
:- pred code_info__stack_variable_reference(int, rval, code_info, code_info).
@@ -3332,10 +3315,9 @@
code_info__stack_variable_reference(Num, mem_addr(Ref)) -->
code_info__get_proc_model(CodeModel),
( { CodeModel = model_non } ->
- { Num1 is Num - 1 }, % framevars start at zero
- { Ref = framevar_ref(Num1) }
+ { Ref = framevar_ref(Num) }
;
- { Ref = stackvar_ref(Num) } % stackvars start at one
+ { Ref = stackvar_ref(Num) }
).
%---------------------------------------------------------------------------%
Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.14
diff -u -u -r1.14 continuation_info.m
--- continuation_info.m 1998/07/15 12:20:53 1.14
+++ continuation_info.m 1998/08/12 09:27:08
@@ -63,18 +63,23 @@
%
:- type proc_layout_info
---> proc_layout_info(
- label, % the entry 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,
+ label, % The entry label.
+ determinism, % Determines which stack is used.
+ int, % Number of stack slots.
+ maybe(int), % Location of succip on stack.
+ maybe(label), % If the trace level is not none,
% 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.
+ maybe(int), % If the trace level is shallow,
+ % this contains the number of the
+ % stack slot containing the
+ % value of MR_trace_full_full
+ % at the time of the call.
proc_label_layout_info
- % info for each internal label,
- % needed for basic_stack_layouts
+ % Info for each internal label,
+ % needed for basic_stack_layouts.
).
%
@@ -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.
@@ -176,7 +180,7 @@
%
:- pred continuation_info__add_proc_info(pred_proc_id::in, label::in,
int::in, determinism::in, maybe(int)::in, maybe(label)::in,
- proc_label_layout_info::in, continuation_info::in,
+ maybe(int)::in, proc_label_layout_info::in, continuation_info::in,
continuation_info::out) is det.
%
@@ -227,13 +231,14 @@
% continuation_info.
%
continuation_info__add_proc_info(PredProcId, EntryLabel, StackSize,
- Detism, SuccipLocation, MaybeTraceCallLabel, InternalMap,
- ContInfo0, ContInfo) :-
+ Detism, SuccipLocation, MaybeTraceCallLabel,
+ MaybeFromFullSlot, InternalMap, ContInfo0, ContInfo) :-
( map__contains(ContInfo0, PredProcId) ->
error("duplicate continuation_info for proc.")
;
LayoutInfo = proc_layout_info(EntryLabel, Detism, StackSize,
- SuccipLocation, MaybeTraceCallLabel, InternalMap),
+ SuccipLocation, MaybeTraceCallLabel,
+ MaybeFromFullSlot, InternalMap),
map__det_insert(ContInfo0, PredProcId, LayoutInfo, ContInfo)
).
@@ -259,7 +264,7 @@
% Get all the continuation info from the call instructions.
map__lookup(ContInfo0, PredProcId, ProcLayoutInfo0),
- ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, Internals0),
+ ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, F, Internals0),
GetCallLivevals = lambda([Instr::in, Pair::out] is semidet, (
Instr = call(_, label(Label), LiveInfo, _) - _Comment,
Pair = Label - LiveInfo
@@ -270,7 +275,7 @@
list__foldl(continuation_info__process_continuation(WantReturnInfo),
Calls, Internals0, Internals),
- ProcLayoutInfo = proc_layout_info(A, B, C, D, E, Internals),
+ ProcLayoutInfo = proc_layout_info(A, B, C, D, E, F, Internals),
map__det_update(ContInfo0, PredProcId, ProcLayoutInfo, ContInfo).
%-----------------------------------------------------------------------------%
@@ -320,12 +325,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 +345,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/dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.35
diff -u -u -r1.35 dupelim.m
--- dupelim.m 1998/07/29 08:52:59 1.35
+++ dupelim.m 1998/08/13 02:16:42
@@ -945,6 +945,7 @@
dupelim__replace_labels_code_addr(do_succeed(Last), _, do_succeed(Last)).
dupelim__replace_labels_code_addr(do_redo, _, do_redo).
dupelim__replace_labels_code_addr(do_fail, _, do_fail).
+dupelim__replace_labels_code_addr(do_trace_redo_fail, _, do_trace_redo_fail).
dupelim__replace_labels_code_addr(do_det_closure, _, do_det_closure).
dupelim__replace_labels_code_addr(do_semidet_closure, _, do_semidet_closure).
dupelim__replace_labels_code_addr(do_nondet_closure, _, do_nondet_closure).
Index: compiler/exprn_aux.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/exprn_aux.m,v
retrieving revision 1.29
diff -u -u -r1.29 exprn_aux.m
--- exprn_aux.m 1998/07/20 10:00:41 1.29
+++ exprn_aux.m 1998/08/13 02:16:55
@@ -147,6 +147,7 @@
exprn_aux__addr_is_constant(do_succeed(_), _, no).
exprn_aux__addr_is_constant(do_redo, _, no).
exprn_aux__addr_is_constant(do_fail, _, no).
+exprn_aux__addr_is_constant(do_trace_redo_fail, _, no).
exprn_aux__addr_is_constant(do_det_closure, _, no).
exprn_aux__addr_is_constant(do_semidet_closure, _, no).
exprn_aux__addr_is_constant(do_nondet_closure, _, no).
Index: compiler/globals.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/globals.m,v
retrieving revision 1.31
diff -u -u -r1.31 globals.m
--- globals.m 1998/06/18 06:06:09 1.31
+++ globals.m 1998/09/16 05:09:51
@@ -46,11 +46,10 @@
; num_data_elems
; size_data_elems.
-:- type trace_level.
-
-:- pred trace_level_trace_interface(trace_level::in, bool::out) is det.
-:- pred trace_level_trace_ports(trace_level::in, bool::out) is det.
-:- pred trace_level_trace_returns(trace_level::in, bool::out) is det.
+:- type trace_level
+ ---> none
+ ; shallow
+ ; deep.
:- pred convert_gc_method(string::in, gc_method::out) is semidet.
:- pred convert_tags_method(string::in, tags_method::out) is semidet.
@@ -100,10 +99,14 @@
% More complex options
% Check if static code addresses are available in the
- % current grade of compilation
+ % current grade of compilation.
:- pred globals__have_static_code_addresses(globals::in, bool::out) is det.
+ % Check if we should generate stack layouts at call return sites.
+
+:- pred globals__want_return_layouts(globals::in, bool::out) is det.
+
%-----------------------------------------------------------------------------%
% Access predicates for storing a `globals' structure in the
@@ -169,29 +172,6 @@
:- import_module exprn_aux.
:- import_module map, std_util, io, require.
-:- type trace_level
- ---> none
- ; interface
- ; interface_ports
- ; interface_ports_returns.
-
-trace_level_trace_interface(none, no).
-trace_level_trace_interface(interface, yes).
-trace_level_trace_interface(interface_ports, yes).
-trace_level_trace_interface(interface_ports_returns, yes).
-
-trace_level_trace_ports(none, no).
-trace_level_trace_ports(interface, no).
-trace_level_trace_ports(interface_ports, yes).
-trace_level_trace_ports(interface_ports_returns, yes).
-
-trace_level_trace_returns(none, no).
-trace_level_trace_returns(interface, no).
-trace_level_trace_returns(interface_ports, no).
-trace_level_trace_returns(interface_ports_returns, yes).
-
-%-----------------------------------------------------------------------------%
-
convert_gc_method("none", none).
convert_gc_method("conservative", conservative).
convert_gc_method("accurate", accurate).
@@ -223,12 +203,11 @@
convert_termination_norm("size-data-elems", size_data_elems).
convert_trace_level("minimum", no, none).
-convert_trace_level("minimum", yes, interface).
-convert_trace_level("interfaces", _, interface).
-convert_trace_level("most", _, interface_ports).
-convert_trace_level("all", _, interface_ports_returns).
+convert_trace_level("minimum", yes, shallow).
+convert_trace_level("shallow", _, shallow).
+convert_trace_level("deep", _, deep).
convert_trace_level("default", no, none).
-convert_trace_level("default", yes, interface_ports).
+convert_trace_level("default", yes, deep).
%-----------------------------------------------------------------------------%
@@ -316,6 +295,26 @@
NonLocalGotos),
getopt__lookup_bool_option(OptionTable, asm_labels, AsmLabels),
exprn_aux__imported_is_constant(NonLocalGotos, AsmLabels, IsConst).
+
+globals__want_return_layouts(Globals, WantReturnLayouts) :-
+ % We need to generate layout info for call return labels
+ % if we are using accurate gc or if the user wants uplevel printing.
+ (
+ (
+ globals__get_gc_method(Globals, GC_Method),
+ GC_Method = accurate
+ ;
+ globals__lookup_bool_option(Globals, trace_return,
+ TraceReturn),
+ TraceReturn = yes,
+ globals__get_trace_level(Globals, TraceLevel),
+ TraceLevel \= none
+ )
+ ->
+ WantReturnLayouts = yes
+ ;
+ WantReturnLayouts = no
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.61
diff -u -u -r1.61 handle_options.m
--- handle_options.m 1998/09/10 06:51:06 1.61
+++ handle_options.m 1998/09/16 05:03:01
@@ -32,7 +32,6 @@
% Display long usage message for help
:- pred long_usage(io__state::di, io__state::uo) is det.
-
% Given the current set of options, figure out
% which grade to use.
:- pred compute_grade(globals::in, string::out) is det.
@@ -282,37 +281,48 @@
% be able to afford the minor performance hit caused by
% --use-trail.
- globals__io_lookup_bool_option(stack_trace, StackTrace),
- globals__io_lookup_bool_option(require_tracing, RequireTracing),
- ( { StackTrace = yes, RequireTracing = yes } ->
- globals__io_set_option(use_trail, bool(yes))
- ;
- []
- ),
+% This does work at the moment, since turning on --use-trail causes the
+% generated code to refer to variables such as MR_trail_ptr_var. These
+% variables are supposed to be supplied by a library that looks after the
+% trail, e.g. a constraint library. However, we don't yet have a mechanism
+% for linking in such a library when the grade includes `.debug'.
+% globals__io_lookup_bool_option(stack_trace, StackTrace),
+% globals__io_lookup_bool_option(require_tracing, RequireTracing),
+% ( { StackTrace = yes, RequireTracing = yes } ->
+% globals__io_set_option(use_trail, bool(yes))
+% ;
+% []
+% ),
% Execution tracing requires
% - disabling optimizations that would change
- % the trace being generated
+ % the trace being generated (except with --trace-optimized)
% - enabling some low level optimizations to ensure consistent
% paths across optimization levels
% - enabling stack layouts
% - enabling typeinfo liveness
- ( { trace_level_trace_interface(TraceLevel, yes) } ->
+ globals__io_lookup_bool_option(trace_optimized, TraceOptimized),
+ ( { TraceLevel \= none } ->
+ ( { TraceOptimized = no } ->
% The following options modify the structure
% of the program, which makes it difficult to
% relate the trace to the source code (although
% it can be easily related to the transformed HLDS).
- globals__io_set_option(inline_simple, bool(no)),
- globals__io_set_option(inline_single_use, bool(no)),
- globals__io_set_option(inline_compound_threshold, int(0)),
- globals__io_set_option(optimize_unused_args, bool(no)),
- globals__io_set_option(optimize_higher_order, bool(no)),
- globals__io_set_option(type_specialization, bool(no)),
- globals__io_set_option(deforestation, bool(no)),
- globals__io_set_option(optimize_duplicate_calls, bool(no)),
- globals__io_set_option(optimize_constructor_last_call,
- bool(no)),
-
+ globals__io_set_option(inline_simple, bool(no)),
+ globals__io_set_option(inline_single_use, bool(no)),
+ globals__io_set_option(inline_compound_threshold,
+ int(0)),
+ globals__io_set_option(optimize_unused_args, bool(no)),
+ globals__io_set_option(optimize_higher_order, bool(no)),
+ globals__io_set_option(type_specialization, bool(no)),
+ globals__io_set_option(deforestation, bool(no)),
+ globals__io_set_option(optimize_duplicate_calls,
+ bool(no)),
+ globals__io_set_option(optimize_constructor_last_call,
+ bool(no))
+ ;
+ []
+ ),
% The following option prevents useless variables
% from cluttering the trace. Its explicit setting
% removes a source of variability in the goal paths
@@ -632,7 +642,6 @@
% Trailing components
grade_component_table("tr", trail, [use_trail - bool(yes)]).
-
:- pred split_grade_string(string, list(string)).
:- mode split_grade_string(in, out) is semidet.
Index: compiler/live_vars.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/live_vars.m,v
retrieving revision 1.78
diff -u -u -r1.78 live_vars.m
--- live_vars.m 1998/08/07 00:49:00 1.78
+++ live_vars.m 1998/08/08 08:07:28
@@ -50,18 +50,19 @@
set__init(LiveSets0),
module_info_globals(ModuleInfo, Globals),
globals__get_trace_level(Globals, TraceLevel),
- ( trace_level_trace_interface(TraceLevel, yes) ->
+ ( TraceLevel \= none ->
trace__fail_vars(ModuleInfo, ProcInfo0, ResumeVars0),
set__insert(LiveSets0, ResumeVars0, LiveSets1)
;
set__init(ResumeVars0),
LiveSets1 = LiveSets0
),
+ trace__reserved_slots(ProcInfo0, Globals, ReservedSlots),
build_live_sets_in_goal(Goal0, Liveness0, ResumeVars0, LiveSets1,
ModuleInfo, ProcInfo0, _Liveness, _ResumeVars, LiveSets),
graph_colour__group_elements(LiveSets, ColourSets),
set__to_sorted_list(ColourSets, ColourList),
- allocate_stack_slots(ColourList, CodeModel, StackSlots),
+ allocate_stack_slots(ColourList, CodeModel, ReservedSlots, StackSlots),
proc_info_set_stack_slots(ProcInfo0, StackSlots, ProcInfo).
@@ -582,19 +583,15 @@
%-----------------------------------------------------------------------------%
-:- pred allocate_stack_slots(list(set(var)), code_model, stack_slots).
-:- mode allocate_stack_slots(in, in, out) is det.
+:- pred allocate_stack_slots(list(set(var)), code_model, int, stack_slots).
+:- mode allocate_stack_slots(in, in, in, out) is det.
-allocate_stack_slots(ColourList, CodeModel, StackSlots) :-
+allocate_stack_slots(ColourList, CodeModel, ReservedSlots, StackSlots) :-
map__init(StackSlots0),
- (
- CodeModel = model_non
- ->
- First = 0
- ;
- First = 1
- ),
- allocate_stack_slots_2(ColourList, First, CodeModel,
+ % The reserved slots are referred to by fixed number
+ % (e.g. framevar(1)) in trace__setup.
+ FirstVarSlot is 1 + ReservedSlots,
+ allocate_stack_slots_2(ColourList, FirstVarSlot, CodeModel,
StackSlots0, StackSlots).
:- pred allocate_stack_slots_2(list(set(var)), int, code_model,
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.37
diff -u -u -r1.37 livemap.m
--- livemap.m 1998/07/29 08:53:10 1.37
+++ livemap.m 1998/08/13 02:16:18
@@ -393,6 +393,7 @@
livemap__special_code_addr(succip, yes(succip)).
livemap__special_code_addr(do_succeed(_), yes(succip(lval(curfr)))).
livemap__special_code_addr(do_redo, yes(redoip(lval(maxfr)))).
+livemap__special_code_addr(do_trace_redo_fail, no).
livemap__special_code_addr(do_fail, no).
livemap__special_code_addr(do_det_closure, no).
livemap__special_code_addr(do_semidet_closure, no).
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.97
diff -u -u -r1.97 liveness.m
--- liveness.m 1998/06/18 06:06:26 1.97
+++ liveness.m 1998/08/08 08:30:42
@@ -182,7 +182,7 @@
detect_deadness_in_goal(Goal1, Deadness0, LiveInfo, _, Goal2),
globals__get_trace_level(Globals, TraceLevel),
- ( trace_level_trace_interface(TraceLevel, yes) ->
+ ( TraceLevel \= none ->
trace__fail_vars(ModuleInfo, ProcInfo0, ResumeVars0)
;
set__init(ResumeVars0)
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.228
diff -u -u -r1.228 llds.m
--- llds.m 1998/09/03 11:13:27 1.228
+++ llds.m 1998/09/04 00:04:15
@@ -427,10 +427,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
@@ -442,16 +438,22 @@
% 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
- ; redofr
- ; 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.
+ ; redofr % A stored redofr.
+ ; hp % A stored head pointer.
+ ; var(var, string, type, inst) % A variable (the var number
+ % and name are for execution
+ % tracing; we have to store
+ % the name here because when
+ % we want to use the
+ % live_value_type, we won't
+ % have access to the varset).
+ ; 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.
@@ -707,22 +709,28 @@
; exported(proc_label). % exported from Mercury module
:- type code_addr
- ---> label(label) % a label defined in this Mercury module
- ; imported(proc_label) % a label from another Mercury module
- ; succip % the address in the `succip' register
- ; do_succeed(bool) % the bool is `yes' if there are any
+ ---> label(label) % A label defined in this Mercury
+ % module.
+ ; imported(proc_label) % A label from another Mercury module.
+ ; succip % The address in the `succip'
+ % register.
+ ; do_succeed(bool) % The bool is `yes' if there are any
% alternatives left. If the bool is
% `no', we do a succeed_discard()
% rather than a succeed().
; do_redo
; do_fail
+ ; do_trace_redo_fail
+ % A label in the runtime, the code
+ % at which calls MR_trace with a
+ % REDO event and then fails.
; do_det_closure
; do_semidet_closure
; do_nondet_closure
; do_det_class_method
; do_semidet_class_method
; do_nondet_class_method
- ; do_not_reached. % we should never jump to this address
+ ; do_not_reached. % We should never jump to this address.
% A proc_label is a label used for the entry point to a procedure.
% The defining module is the module that provides the code for the
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.88
diff -u -u -r1.88 llds_out.m
--- llds_out.m 1998/09/03 11:13:29 1.88
+++ llds_out.m 1998/09/04 00:04:17
@@ -34,9 +34,13 @@
:- pred llds_out__lval_to_string(lval, string).
:- mode llds_out__lval_to_string(in, out) is semidet.
+ % Convert a register to a string description of that register.
+
:- pred llds_out__reg_to_string(reg_type, int, string).
:- mode llds_out__reg_to_string(in, in, out) is det.
+ % Convert a binary operator to a string description of that operator.
+
:- pred llds_out__binary_op_to_string(binary_op, string).
:- mode llds_out__binary_op_to_string(in, out) is det.
@@ -106,6 +110,12 @@
:- pred llds_out__make_base_typeclass_info_name(class_id, string, string).
:- mode llds_out__make_base_typeclass_info_name(in, in, out) is det.
+ % Convert a label to a string description of the stack layout
+ % structure of that label.
+
+:- pred llds_out__make_stack_layout_name(label, string).
+:- mode llds_out__make_stack_layout_name(in, out) is det.
+
% Returns the name of the initialization function
% for a given module.
@@ -221,7 +231,7 @@
io__write_string("#undef MR_USE_REDOFR\n"),
io__write_string("#define MR_USE_REDOFR\n"),
globals__io_get_trace_level(TraceLevel),
- ( { trace_level_trace_interface(TraceLevel, yes) } ->
+ ( { TraceLevel \= none } ->
io__write_string("#define MR_STACK_TRACE_THIS_MODULE\n"),
io__write_string("#include ""mercury_imp.h""\n"),
io__write_string("#include ""mercury_trace.h""\n")
@@ -1508,12 +1518,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),
@@ -1542,8 +1550,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(", "),
@@ -2069,6 +2079,7 @@
{ UseMacro = no },
{ NeedDecl = yes }
).
+need_code_addr_decls(do_trace_redo_fail, yes) --> [].
need_code_addr_decls(do_det_closure, yes) --> [].
need_code_addr_decls(do_semidet_closure, yes) --> [].
need_code_addr_decls(do_nondet_closure, yes) --> [].
@@ -2108,6 +2119,8 @@
io__write_string("do_fail"),
io__write_string(");\n")
).
+output_code_addr_decls(do_trace_redo_fail) -->
+ io__write_string("Declare_entry(MR_do_trace_redo_fail);\n").
output_code_addr_decls(do_det_closure) -->
io__write_string("Declare_entry(do_call_det_closure);\n").
output_code_addr_decls(do_semidet_closure) -->
@@ -2311,6 +2324,8 @@
{ UseMacro = no },
io__write_string("GOTO(ENTRY(do_fail));\n")
).
+output_goto(do_trace_redo_fail, _) -->
+ io__write_string("GOTO(ENTRY(MR_do_trace_redo_fail));\n").
output_goto(do_det_closure, CallerLabel) -->
io__write_string("tailcall(ENTRY(do_call_det_closure),\n\t\t"),
output_label_as_code_addr(CallerLabel),
@@ -2400,6 +2415,8 @@
io__write_string("ENTRY(do_redo)").
output_code_addr(do_fail) -->
io__write_string("ENTRY(do_fail)").
+output_code_addr(do_trace_redo_fail) -->
+ io__write_string("ENTRY(MR_do_trace_redo_fail)").
output_code_addr(do_det_closure) -->
io__write_string("ENTRY(do_call_det_closure)").
output_code_addr(do_semidet_closure) -->
@@ -2415,6 +2432,14 @@
output_code_addr(do_not_reached) -->
io__write_string("ENTRY(do_not_reached)").
+ % The code should be kept in sync with output_data_addr/2 below.
+llds_out__make_stack_layout_name(Label, Name) :-
+ llds_out__get_label(Label, yes, LabelName),
+ string__append_list([
+ "mercury_data_",
+ "_layout__",
+ LabelName
+ ], Name).
% Output a data address.
@@ -2449,6 +2474,7 @@
io__write_string("__"),
io__write_string(Str)
;
+ % Keep this code in sync with make_stack_layout_name/3.
{ VarName = stack_layout(Label) },
io__write_string("_layout__"),
output_label(Label)
@@ -3086,14 +3112,13 @@
io__write_int(N),
io__write_string(")").
output_lval(framevar(N)) -->
- { (N < 0) ->
+ { (N =< 0) ->
error("frame var out of range")
;
true
},
io__write_string("MR_framevar("),
- { N1 is N + 1 },
- io__write_int(N1),
+ io__write_int(N),
io__write_string(")").
output_lval(succip) -->
io__write_string("succip").
@@ -3228,8 +3253,7 @@
%-----------------------------------------------------------------------------%
llds_out__lval_to_string(framevar(N), Description) :-
- N1 is N + 1,
- string__int_to_string(N1, N_String),
+ string__int_to_string(N, N_String),
string__append("MR_framevar(", N_String, Tmp),
string__append(Tmp, ")", Description).
llds_out__lval_to_string(stackvar(N), Description) :-
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.106
diff -u -u -r1.106 mercury_compile.m
--- mercury_compile.m 1998/09/10 06:51:23 1.106
+++ mercury_compile.m 1998/09/16 05:09:49
@@ -1145,7 +1145,7 @@
PredId, ProcId, ModuleInfo3),
{ store_alloc_in_proc(ProcInfo5, PredId, ModuleInfo3, ProcInfo6) },
globals__io_get_trace_level(TraceLevel),
- ( { trace_level_trace_interface(TraceLevel, yes) } ->
+ ( { TraceLevel \= none } ->
write_proc_progress_message(
"% Calculating goal paths in ",
PredId, ProcId, ModuleInfo3),
@@ -1177,18 +1177,10 @@
write_proc_progress_message(
"% Generating call continuation information for ",
PredId, ProcId, ModuleInfo5),
- { globals__get_gc_method(Globals, GcMethod) },
- {
- ( GcMethod = accurate
- ; trace_level_trace_returns(TraceLevel, yes)
- )
- ->
- WantReturnInfo = yes
- ;
- WantReturnInfo = no
- },
+ { globals__want_return_layouts(Globals, WantReturnLayout) },
{ continuation_info__process_instructions(PredProcId,
- Instructions, WantReturnInfo, ContInfo2, ContInfo3) },
+ Instructions, WantReturnLayout,
+ ContInfo2, ContInfo3) },
{ module_info_set_continuation_info(ModuleInfo5, ContInfo3,
ModuleInfo) }
;
@@ -1794,7 +1786,7 @@
mercury_compile__maybe_goal_paths(HLDS0, Verbose, Stats, HLDS) -->
globals__io_get_trace_level(TraceLevel),
- ( { trace_level_trace_interface(TraceLevel, yes) } ->
+ ( { TraceLevel \= none } ->
maybe_write_string(Verbose, "% Calculating goal paths..."),
maybe_flush_output(Verbose),
process_all_nonimported_procs(
@@ -1846,19 +1838,10 @@
maybe_write_string(Verbose,
"% Generating call continuation information..."),
maybe_flush_output(Verbose),
- globals__io_get_gc_method(GcMethod),
- globals__io_get_trace_level(TraceLevel),
- {
- ( GcMethod = accurate
- ; trace_level_trace_returns(TraceLevel, yes)
- )
- ->
- WantReturnInfo = yes
- ;
- WantReturnInfo = no
- },
+ globals__io_get_globals(Globals),
+ { globals__want_return_layouts(Globals, WantReturnLayout) },
{ module_info_get_continuation_info(ModuleInfo0, ContInfo0) },
- { continuation_info__process_llds(LLDS0, WantReturnInfo,
+ { continuation_info__process_llds(LLDS0, WantReturnLayout,
ContInfo0, ContInfo) },
{ module_info_set_continuation_info(ModuleInfo0, ContInfo,
ModuleInfo) },
@@ -2369,7 +2352,7 @@
maybe_write_string(Verbose, "% Creating initialization file...\n"),
join_module_list(Modules, ".m", ["> ", InitCFileName], MkInitCmd0),
globals__io_get_trace_level(TraceLevel),
- { trace_level_trace_interface(TraceLevel, yes) ->
+ { TraceLevel \= none ->
CmdPrefix = "c2init -i "
;
CmdPrefix = "c2init "
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.84
diff -u -u -r1.84 opt_debug.m
--- opt_debug.m 1998/07/29 08:53:30 1.84
+++ opt_debug.m 1998/08/13 04:06:27
@@ -754,6 +754,7 @@
).
opt_debug__dump_code_addr(do_redo, "do_redo").
opt_debug__dump_code_addr(do_fail, "do_fail").
+opt_debug__dump_code_addr(do_trace_redo_fail, "do_trace_redo_fail").
opt_debug__dump_code_addr(do_det_closure, "do_det_closure").
opt_debug__dump_code_addr(do_semidet_closure, "do_semidet_closure").
opt_debug__dump_code_addr(do_nondet_closure, "do_nondet_closure").
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.95
diff -u -u -r1.95 opt_util.m
--- opt_util.m 1998/07/29 08:53:33 1.95
+++ opt_util.m 1998/08/13 04:06:45
@@ -1281,6 +1281,7 @@
opt_util__livevals_addr(do_succeed(_), yes).
opt_util__livevals_addr(do_redo, no).
opt_util__livevals_addr(do_fail, no).
+opt_util__livevals_addr(do_trace_redo_fail, no).
opt_util__livevals_addr(do_det_closure, yes).
opt_util__livevals_addr(do_semidet_closure, yes).
opt_util__livevals_addr(do_nondet_closure, yes).
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.240
diff -u -u -r1.240 options.m
--- options.m 1998/09/10 06:51:30 1.240
+++ options.m 1998/09/16 05:00:58
@@ -90,6 +90,10 @@
% Auxiliary output options
; assume_gmake
; trace
+ ; trace_internal
+ ; trace_return
+ ; trace_redo
+ ; trace_optimized
; generate_bytecode
; generate_prolog
; prolog_dialect
@@ -374,6 +378,10 @@
% Auxiliary Output Options
assume_gmake - bool(yes),
trace - string("default"),
+ trace_internal - bool(yes),
+ trace_return - bool(yes),
+ trace_redo - bool(yes),
+ trace_optimized - bool(no),
generate_bytecode - bool(no),
generate_prolog - bool(no),
prolog_dialect - string("default"),
@@ -703,6 +711,11 @@
% aux output options
long_option("assume-gmake", assume_gmake).
long_option("trace", trace).
+long_option("trace-internal", trace_internal).
+long_option("trace-return", trace_return).
+long_option("trace-redo", trace_redo).
+long_option("trace-optimised", trace_optimized).
+long_option("trace-optimized", trace_optimized).
long_option("generate-bytecode", generate_bytecode).
long_option("generate-prolog", generate_prolog).
long_option("generate-Prolog", generate_prolog).
@@ -743,10 +756,8 @@
long_option("profile-time", profile_time).
long_option("profile-memory", profile_memory).
long_option("debug", debug).
-% The following options are not allowed, because they're
-% not very useful and would probably only confuse people.
-% long_option("stack-trace", stack_trace).
-% long_option("require-tracing", require_tracing).
+long_option("stack-trace", stack_trace).
+long_option("require-tracing", require_tracing).
long_option("use-trail", use_trail).
long_option("pic-reg", pic_reg).
long_option("tags", tags).
@@ -1376,11 +1387,21 @@
"\tWhen generating `.dep' files, generate Makefile",
"\tfragments that use only the features of standard make;",
"\tdo not assume the availability of GNU Make extensions.",
- "--trace {minimum, interfaces, all, default}",
+ "--trace {minimum, shallow, deep, default}",
"\tGenerate code that includes the specified level",
"\tof execution tracing.",
- "\tSee the [XXX not yet written!] chapter of the",
- "\tMercury User's Guide for details.",
+ "\tSee the Debugging chapter of the Mercury User's Guide for details.",
+ "--no-trace-internal",
+ "\tDo not generate code for internal events even if the trace",
+ "\tlevel is deep.",
+ "--no-trace-return",
+ "\tDo not generate trace information for call return sites.",
+ "\tPrevents the printing of the values of variables in ancestors",
+ "\tof the current call.",
+ "--no-trace-redo",
+ "\tDo not generate code for REDO events.",
+ "--trace-optimized",
+ "\tDo not disable optimizations that can change the trace.",
"--generate-bytecode",
"\tOutput a bytecode form of the module for use",
"\tby an experimental debugger.",
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.18
diff -u -u -r1.18 stack_layout.m
--- stack_layout.m 1998/09/03 11:13:30 1.18
+++ stack_layout.m 1998/09/04 00:04:25
@@ -68,11 +68,13 @@
% 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
+% maybe from full (Integer) - stack slot of the from_full
+% flag, if the procedure is shallow traced
%
-% 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
@@ -80,6 +82,13 @@
% (If trace_stack_layout is not set, this field will be present,
% but it will be set to NULL.)
%
+% If the procedure is compiled with deep tracing, the last field will contain
+% a negative number. If it is compiled with shallow tracing, it will contain
+% the number of the stack slot that holds the flag that says whether this
+% incarnation of the procedure was called from deeply traced code or not.
+% (The determinism of the procedure decides whether the stack slot refers
+% to a stackvar or a framevar.)
+%
% 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
% global variable whose name is
@@ -222,9 +231,10 @@
stack_layout__construct_layouts(ProcLayoutInfo) -->
{ ProcLayoutInfo = proc_layout_info(EntryLabel, Detism,
- StackSlots, SuccipLoc, CallLabel, InternalMap) },
+ StackSlots, SuccipLoc, MaybeCallLabel, MaybeFromFullSlot,
+ InternalMap) },
stack_layout__construct_proc_layout(EntryLabel, Detism,
- StackSlots, SuccipLoc, CallLabel),
+ StackSlots, SuccipLoc, MaybeCallLabel, MaybeFromFullSlot),
{ map__to_assoc_list(InternalMap, Internals) },
list__foldl(stack_layout__construct_internal_layout(EntryLabel),
Internals).
@@ -235,10 +245,10 @@
:- pred stack_layout__construct_proc_layout(label::in,
determinism::in, int::in, maybe(int)::in, maybe(label)::in,
- stack_layout_info::in, stack_layout_info::out) is det.
+ maybe(int)::in, stack_layout_info::in, stack_layout_info::out) is det.
stack_layout__construct_proc_layout(EntryLabel, Detism, StackSlots,
- MaybeSuccipLoc, MaybeCallLabel) -->
+ MaybeSuccipLoc, MaybeCallLabel, MaybeFromFullSlot) -->
{
MaybeSuccipLoc = yes(Location0)
->
@@ -298,21 +308,27 @@
stack_layout__get_module_name(ModuleName),
stack_layout__get_trace_stack_layout(TraceLayout),
- (
- { TraceLayout = yes }
+ {
+ TraceLayout = yes
->
- ( { MaybeCallLabel = yes(CallLabel) } ->
- { CallRval = yes(const(data_addr_const(
- data_addr(ModuleName,
- stack_layout(CallLabel))))) },
- { list__append(MaybeRvals1, [CallRval], MaybeRvals) }
+ ( MaybeCallLabel = yes(CallLabel) ->
+ CallRval = yes(const(data_addr_const(
+ data_addr(ModuleName,
+ stack_layout(CallLabel)))))
;
- { error("stack_layout__construct_proc_layout: call label not present") }
- )
+ error("stack_layout__construct_proc_layout: call label not present")
+ ),
+ ( MaybeFromFullSlot = yes(FromFullSlot) ->
+ FromFullRval = yes(const(int_const(FromFullSlot)))
+ ;
+ FromFullRval = yes(const(int_const(-1)))
+ ),
+ list__append(MaybeRvals1, [CallRval, FromFullRval],
+ MaybeRvals)
;
- { NoCallRval = yes(const(int_const(0))) },
- { list__append(MaybeRvals1, [NoCallRval], MaybeRvals) }
- ),
+ NoCallRval = yes(const(int_const(0))),
+ list__append(MaybeRvals1, [NoCallRval], MaybeRvals)
+ },
{ Exported = no }, % XXX With the new profiler, we will need to
% set this to `yes' if the profiling option
@@ -507,8 +523,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(_) )
)),
@@ -529,14 +545,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)
@@ -548,6 +566,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
@@ -605,7 +633,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),
@@ -614,13 +642,26 @@
:- 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 \= ""
+ ->
+ % We include a representation of the variable number at the
+ % start of the variable name, because some functions of the
+ % debugger (e.g. restart) require it to be able to distinguish
+ % between distinct variables that happen to have the same name.
+ % We represent the number as a string, because most variable
+ % numbers are so small that this is a very compact
+ % representation.
+ 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).
@@ -631,7 +672,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
@@ -655,7 +696,7 @@
{ Rval = const(int_const(5)) }.
stack_layout__represent_live_value_type(unwanted, Rval) -->
{ Rval = const(int_const(6)) }.
-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/store_alloc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/store_alloc.m,v
retrieving revision 1.66
diff -u -u -r1.66 store_alloc.m
--- store_alloc.m 1998/06/18 06:06:52 1.66
+++ store_alloc.m 1998/08/08 08:07:59
@@ -69,7 +69,7 @@
),
initial_liveness(ProcInfo0, PredId, ModuleInfo, Liveness0),
globals__get_trace_level(Globals, TraceLevel),
- ( trace_level_trace_interface(TraceLevel, yes) ->
+ ( TraceLevel \= none ->
trace__fail_vars(ModuleInfo, ProcInfo0, ResumeVars0)
;
set__init(ResumeVars0)
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.11
diff -u -u -r1.11 trace.m
--- trace.m 1998/07/20 10:01:34 1.11
+++ trace.m 1998/09/14 06:46:06
@@ -47,7 +47,7 @@
:- import_module hlds_goal, hlds_pred, hlds_module.
:- import_module globals, prog_data, llds, code_info.
-:- import_module assoc_list, set, term.
+:- import_module std_util, assoc_list, set, term.
:- type external_trace_port
---> call
@@ -68,16 +68,27 @@
% layouts).
:- pred trace__fail_vars(module_info::in, proc_info::in, set(var)::out) is det.
- % Reserve the stack slots for the call number, call depth and
- % (for interface tracing) for the flag that says whether this call
- % should be traced. Return our (abstract) struct that says which
- % slots these are, so that it can be made part of the code generator
- % state.
-:- pred trace__setup(trace_level::in, trace_info::out,
+ % Return the number of slots reserved for tracing information.
+ % If there are N slots, the reserved slots will be 1 through N.
+:- pred trace__reserved_slots(proc_info::in, globals::in, int::out) is det.
+
+ % Reserve the non-fixed stack slots needed for tracing.
+ % The fixed slots for the event number, call number, call depth and
+ % (for trace levels that specify redo events) the stack layout of
+ % the redo event are reserved in live_vars.m; this predicate reserved
+ % only the slots that do not need to be in fixed slots. At the moment
+ % the only such slot is the flag that says whether this call should be
+ % traced, which is required only for shallow tracing.
+ %
+ % The predicate returns the number of this slot if it is used,
+ % an abstract struct that represents the tracing-specific part
+ % of the code generator state.
+:- pred trace__setup(globals::in, maybe(int)::out, trace_info::out,
code_info::in, code_info::out) is det.
% Generate code to fill in the reserevd stack slots.
-:- pred trace__generate_slot_fill_code(trace_info::in, code_tree::out) is det.
+:- pred trace__generate_slot_fill_code(trace_info::in, code_tree::out,
+ code_info::in, code_info::out) is det.
% If we are doing execution tracing, generate code to prepare for
% a call.
@@ -104,6 +115,12 @@
trace_info::in, label::out, assoc_list(tvar, lval)::out, code_tree::out,
code_info::in, code_info::out) is det.
+ % If the trace level calls for redo events, generate code that pushes
+ % a temporary nondet stack frame whose redoip slot contains the
+ % address of one of the labels in the runtime that calls MR_trace
+ % for a redo event. Otherwise, generate empty code.
+:- pred trace__maybe_setup_redo_event(trace_info::in, code_tree::out) is det.
+
:- pred trace__path_to_string(goal_path::in, string::out) is det.
%-----------------------------------------------------------------------------%
@@ -111,7 +128,7 @@
:- implementation.
:- import_module continuation_info, type_util, llds_out, tree.
-:- import_module (inst), instmap, inst_match, mode_util.
+:- import_module (inst), instmap, inst_match, mode_util, options.
:- import_module list, bool, int, string, map, std_util, varset, require.
:- type trace_port
@@ -136,8 +153,8 @@
; nondet_pragma.
:- type trace_type
- ---> full_trace
- ; interface_trace(lval). % This holds the saved value of a bool
+ ---> deep_trace
+ ; shallow_trace(lval). % This holds the saved value of a bool
% that is true iff we were called from
% code with full tracing.
@@ -145,9 +162,20 @@
% of a procedure.
:- type trace_info
---> trace_info(
- lval, % stack slot of call sequence number
- lval, % stack slot of call depth
- trace_type
+ trace_type, % The trace level (which cannot be
+ % none), and if it is shallow, the
+ % lval of the slot that holds the
+ % from-full flag.
+ bool, % The value of --trace-internal.
+ bool, % The value of --trace-return.
+ maybe(label) % If we are generating redo events,
+ % this has the label associated with
+ % the fail event, which we then reserve
+ % in advance, so we can put the
+ % address of its layout struct
+ % into the slot which holds the
+ % layout for the redo event (the
+ % two events have identical layouts).
).
trace__fail_vars(ModuleInfo, ProcInfo, FailVars) :-
@@ -163,68 +191,152 @@
;
error("length mismatch in trace__fail_vars")
).
+
+trace__reserved_slots(ProcInfo, Globals, ReservedSlots) :-
+ globals__get_trace_level(Globals, TraceLevel),
+ (
+ TraceLevel = none
+ ->
+ ReservedSlots = 0
+ ;
+ globals__lookup_bool_option(Globals, trace_redo, yes),
+ proc_info_interface_code_model(ProcInfo, model_non)
+ ->
+ ( TraceLevel = deep ->
+ % event#, call#, call depth, redo layout
+ ReservedSlots = 4
+ ;
+ % event#, call#, call depth, redo layout, from full
+ ReservedSlots = 5
+ )
+ ;
+ ( TraceLevel = deep ->
+ % event#, call#, call depth
+ ReservedSlots = 3
+ ;
+ % event#, call#, call depth, from full
+ ReservedSlots = 4
+ )
+ ).
-trace__setup(TraceLevel, TraceInfo) -->
- code_info__acquire_temp_slot(trace_data, CallNumSlot),
- code_info__acquire_temp_slot(trace_data, CallDepthSlot),
- ( { trace_level_trace_ports(TraceLevel, yes) } ->
- { TraceType = full_trace }
+trace__setup(Globals, MaybeFromFullSlot, TraceInfo) -->
+ % These slots were reserved by allocate_stack_slots in live_vars.m.
+ code_info__get_proc_model(CodeModel),
+ { globals__lookup_bool_option(Globals, trace_return, TraceReturn) },
+ { globals__lookup_bool_option(Globals, trace_redo, TraceRedo) },
+ (
+ { TraceRedo = yes },
+ { CodeModel = model_non }
+ ->
+ code_info__get_next_label(RedoLayoutLabel),
+ { MaybeRedoLayoutSlot = yes(RedoLayoutLabel) }
;
- code_info__acquire_temp_slot(trace_data, CallFromFullSlot),
- { TraceType = interface_trace(CallFromFullSlot) }
+ { MaybeRedoLayoutSlot = no }
),
- { TraceInfo = trace_info(CallNumSlot, CallDepthSlot, TraceType) }.
+ { globals__get_trace_level(Globals, deep) ->
+ TraceType = deep_trace,
+ globals__lookup_bool_option(Globals, trace_internal,
+ TraceInternal),
+ MaybeFromFullSlot = no
+ ;
+ % Trace level must be shallow.
+ %
+ % Debugger code in the runtime is not interested in the
+ % call-from-full flag, so does not have to be in a fixed slot.
+ % Even if we put in a fixed slot, the runtime won't know
+ % whether a procedure has interface or full tracing, and so it
+ % wouldn't know whether the slot was used for this purpose
+ % or not.
+ ( CodeModel = model_non ->
+ ( TraceRedo = yes ->
+ CallFromFullSlot = framevar(5),
+ MaybeFromFullSlot = yes(4)
+ ;
+ CallFromFullSlot = framevar(4),
+ MaybeFromFullSlot = yes(4)
+ )
+ ;
+ CallFromFullSlot = stackvar(4),
+ MaybeFromFullSlot = yes(4)
+ ),
+ TraceType = shallow_trace(CallFromFullSlot),
+ % Shallow traced procs never generate internal events.
+ TraceInternal = no
+ },
+ { TraceInfo = trace_info(TraceType, TraceInternal, TraceReturn,
+ MaybeRedoLayoutSlot) }.
-trace__generate_slot_fill_code(TraceInfo, TraceCode) :-
- TraceInfo = trace_info(CallNumLval, CallDepthLval, TraceType),
+trace__generate_slot_fill_code(TraceInfo, TraceCode) -->
+ code_info__get_proc_model(CodeModel),
+ {
+ TraceInfo = trace_info(TraceType, _, _, MaybeRedoLayoutSlot),
+ trace__event_num_slot(CodeModel, EventNumLval),
+ trace__call_num_slot(CodeModel, CallNumLval),
+ trace__call_depth_slot(CodeModel, CallDepthLval),
+ trace__stackref_to_string(EventNumLval, EventNumStr),
trace__stackref_to_string(CallNumLval, CallNumStr),
trace__stackref_to_string(CallDepthLval, CallDepthStr),
+ 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();"
+ ], FillThreeSlots),
+ ( MaybeRedoLayoutSlot = yes(RedoLayoutLabel) ->
+ trace__redo_layout_slot(CodeModel, RedoLayoutLval),
+ trace__stackref_to_string(RedoLayoutLval, RedoLayoutStr),
+ llds_out__make_stack_layout_name(RedoLayoutLabel,
+ LayoutAddrStr),
+ string__append_list([
+ FillThreeSlots, "\n",
+ "\t\t", RedoLayoutStr, " = (Word) (const Word *) &",
+ LayoutAddrStr, ";"
+ ], FillFourSlots)
+ ;
+ FillFourSlots = FillThreeSlots
+ ),
(
- TraceType = interface_trace(CallFromFullSlot),
+ TraceType = shallow_trace(CallFromFullSlot),
trace__stackref_to_string(CallFromFullSlot,
CallFromFullSlotStr),
string__append_list([
"\t\t", CallFromFullSlotStr, " = MR_trace_from_full;\n",
"\t\tif (MR_trace_from_full) {\n",
- "\t\t\t", CallNumStr, " = MR_trace_incr_seq();\n",
- "\t\t\t", CallDepthStr, " = MR_trace_incr_depth();\n",
+ FillFourSlots, "\n",
"\t\t}"
], TraceStmt)
;
- TraceType = full_trace,
- string__append_list([
- "\t\t", CallNumStr, " = MR_trace_incr_seq();\n",
- "\t\t", CallDepthStr, " = MR_trace_incr_depth();"
- ], TraceStmt)
+ TraceType = deep_trace,
+ TraceStmt = FillFourSlots
),
TraceCode = node([
pragma_c([], [pragma_c_raw_code(TraceStmt)],
will_not_call_mercury, no, yes) - ""
- ]).
+ ])
+ }.
trace__prepare_for_call(TraceCode) -->
code_info__get_maybe_trace_info(MaybeTraceInfo),
+ code_info__get_proc_model(CodeModel),
{
MaybeTraceInfo = yes(TraceInfo)
->
- TraceInfo = trace_info(_CallNumLval, CallDepthLval, TraceType),
+ TraceInfo = trace_info(TraceType, _, _, _),
+ trace__call_depth_slot(CodeModel, CallDepthLval),
trace__stackref_to_string(CallDepthLval, CallDepthStr),
- string__append_list(["MR_trace_reset_depth(", CallDepthStr,
- ");\n"],
- ResetDepthStmt),
+ string__append_list([
+ "MR_trace_reset_depth(", CallDepthStr, ");\n"
+ ], ResetDepthStmt),
(
- TraceType = interface_trace(_),
- TraceCode = node([
- c_code("MR_trace_from_full = FALSE;\n") - "",
- c_code(ResetDepthStmt) - ""
- ])
+ TraceType = shallow_trace(_),
+ ResetFromFullStmt = "MR_trace_from_full = FALSE;\n"
;
- TraceType = full_trace,
- TraceCode = node([
- c_code("MR_trace_from_full = TRUE;\n") - "",
- c_code(ResetDepthStmt) - ""
- ])
- )
+ TraceType = deep_trace,
+ ResetFromFullStmt = "MR_trace_from_full = TRUE;\n"
+ ),
+ TraceCode = node([
+ c_code(ResetFromFullStmt) - "",
+ c_code(ResetDepthStmt) - ""
+ ])
;
TraceCode = empty
}.
@@ -233,7 +345,7 @@
code_info__get_maybe_trace_info(MaybeTraceInfo),
(
{ MaybeTraceInfo = yes(TraceInfo) },
- { TraceInfo = trace_info(_, _, full_trace) }
+ { TraceInfo = trace_info(_, yes, _, _) }
->
{ Goal = _ - GoalInfo },
{ goal_info_get_goal_path(GoalInfo, Path) },
@@ -268,7 +380,7 @@
code_info__get_maybe_trace_info(MaybeTraceInfo),
(
{ MaybeTraceInfo = yes(TraceInfo) },
- { TraceInfo = trace_info(_, _, full_trace) }
+ { TraceInfo = trace_info(_, yes, _, _) }
->
{ trace__convert_nondet_pragma_port_type(PragmaPort, Port) },
trace__generate_event_code(Port, nondet_pragma, TraceInfo,
@@ -289,22 +401,41 @@
trace__generate_event_code(Port, PortInfo, TraceInfo, Label, TvarDataList,
Code) -->
- code_info__get_next_label(Label),
+ (
+ { Port = fail },
+ { TraceInfo = trace_info(_, _, _, yes(RedoLabel)) }
+ ->
+ % The layout information for the redo event is the same as
+ % for the fail event; all the non-clobbered inputs in their
+ % stack slots. It is convenient to generate this common layout
+ % when the code generator state is set up for the fail event;
+ % generating it for the redo event would be much harder.
+ % On the other hand, the address of the layout structure
+ % for the redo event should be put into its fixed stack slot
+ % at procedure entry. Therefore trace__setup reserves a label
+ % whose layout structure serves for both the fail and redo
+ % events.
+ { Label = RedoLabel }
+ ;
+ code_info__get_next_label(Label)
+ ),
code_info__get_known_variables(LiveVars0),
- {
- 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 = ""
- },
+ (
+ { PortInfo = external },
+ { LiveVars = LiveVars0 },
+ { PathStr = "" }
+ ;
+ { PortInfo = internal(Path, PreDeaths) },
+ code_info__current_resume_point_vars(ResumeVars),
+ { set__difference(PreDeaths, ResumeVars, RealPreDeaths) },
+ { set__to_sorted_list(RealPreDeaths, RealPreDeathList) },
+ { list__delete_elems(LiveVars0, RealPreDeathList, 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) },
@@ -322,32 +453,23 @@
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),
- trace__stackref_to_string(CallNumLval, CallNumStr),
- trace__stackref_to_string(CallDepthLval, CallDepthStr),
Quote = """",
Comma = ", ",
trace__port_to_string(Port, PortStr),
- (
- TraceType = full_trace,
- FlagStr = "TRUE"
- ;
- TraceType = interface_trace(CallFromFullLval),
- trace__stackref_to_string(CallFromFullLval, FlagStr)
- ),
+ DeclStmt = "\t\tCode *MR_jumpaddr;\n",
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",
+ "\t\tMR_jumpaddr = MR_trace(\n",
+ "\t\t\t(const MR_Stack_Layout_Label *)\n",
"\t\t\t&mercury_data__layout__", LabelStr, Comma, "\n",
- "\t\t\t", PortStr, Comma,
- CallNumStr, Comma,
- CallDepthStr, Comma, "\n",
- "\t\t\t", Quote, PathStr, Quote, Comma,
- MaxRegStr, Comma, FlagStr, ");\n"],
+ "\t\t\t", PortStr, Comma, Quote, PathStr, Quote, Comma,
+ MaxRegStr, ");\n"],
CallStmt),
- string__append_list([SaveStmt, CallStmt, RestoreStmt], TraceStmt),
+ GotoStmt = "\t\tif (MR_jumpaddr != NULL) GOTO(MR_jumpaddr);",
+ string__append_list([DeclStmt, SaveStmt, CallStmt, RestoreStmt,
+ GotoStmt], TraceStmt),
TraceCode =
node([
label(Label)
@@ -367,6 +489,18 @@
},
code_info__add_trace_layout_for_label(Label, LayoutLabelInfo).
+trace__maybe_setup_redo_event(TraceInfo, Code) :-
+ TraceInfo = trace_info(_, _, TraceRedo, _),
+ ( TraceRedo = yes ->
+ Code = node([
+ mkframe(temp_frame(nondet_stack_proc),
+ do_trace_redo_fail)
+ - "set up deep redo event"
+ ])
+ ;
+ Code = empty
+ ).
+
:- pred trace__produce_vars(list(var)::in, varset::in, instmap::in,
set(tvar)::in, set(tvar)::out, list(var_info)::out, code_tree::out,
code_info::in, code_info::out) is det.
@@ -388,8 +522,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)
},
@@ -469,8 +603,7 @@
string__int_to_string(Slot, SlotString),
string__append_list(["MR_stackvar(", SlotString, ")"], LvalStr)
; Lval = framevar(Slot) ->
- Slot1 is Slot + 1,
- string__int_to_string(Slot1, SlotString),
+ string__int_to_string(Slot, SlotString),
string__append_list(["MR_framevar(", SlotString, ")"], LvalStr)
;
error("non-stack lval in stackref_to_string")
@@ -521,3 +654,40 @@
nondet_pragma_first).
trace__convert_nondet_pragma_port_type(nondet_pragma_later,
nondet_pragma_later).
+
+%-----------------------------------------------------------------------------%
+
+:- pred trace__event_num_slot(code_model::in, lval::out) is det.
+:- pred trace__call_num_slot(code_model::in, lval::out) is det.
+:- pred trace__call_depth_slot(code_model::in, lval::out) is det.
+:- pred trace__redo_layout_slot(code_model::in, lval::out) is det.
+
+trace__event_num_slot(CodeModel, EventNumSlot) :-
+ ( CodeModel = model_non ->
+ EventNumSlot = framevar(1)
+ ;
+ EventNumSlot = stackvar(1)
+ ).
+
+trace__call_num_slot(CodeModel, CallNumSlot) :-
+ ( CodeModel = model_non ->
+ CallNumSlot = framevar(2)
+ ;
+ CallNumSlot = stackvar(2)
+ ).
+
+trace__call_depth_slot(CodeModel, CallDepthSlot) :-
+ ( CodeModel = model_non ->
+ CallDepthSlot = framevar(3)
+ ;
+ CallDepthSlot = stackvar(3)
+ ).
+
+trace__redo_layout_slot(CodeModel, RedoLayoutSlot) :-
+ ( CodeModel = model_non ->
+ RedoLayoutSlot = framevar(4)
+ ;
+ error("attempt to access redo layout slot for det or semi procedure")
+ ).
+
+%-----------------------------------------------------------------------------%
cvs diff: Diffing compiler/notes
More information about the developers
mailing list