for review: debugging chapter in the user guide

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Nov 11 20:40:07 AEDT 1998


For review by Fergus, with his TexInFo wizard hat on.

Estimated hours taken: 16

Almost finish the debugging chapter in the user guide.

The two outstanding tasks are documenting --stack-trace-higher-order
(after checking that it works) and documenting mdb startup (after deciding
what it ought to do).

doc/user_guide.texi:
	Almost finish the debugging chapter, and add documentation of the mmake
	options controlling c2init to the level required by the debugging
	chapter.

compiler/handle_options.m:
	Add a new -D control word, paths, which includes just the fields
	necessary for understanding paths in the debugger. This control word
	is referred to by the user guide.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing bytecode/test
cvs diff: Diffing compiler
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.65
diff -u -u -r1.65 handle_options.m
--- handle_options.m	1998/10/27 20:48:14	1.65
+++ handle_options.m	1998/11/03 06:03:53
@@ -736,3 +736,4 @@
 convert_dump_alias("all", "abcdfgilmnprstuvCMPT").
 convert_dump_alias("codegen", "dfnprsu").
 convert_dump_alias("vanessa", "ltuCIU").
+convert_dump_alias("paths", "cP").
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.141
diff -u -u -r1.141 user_guide.texi
--- user_guide.texi	1998/11/05 03:53:04	1.141
+++ user_guide.texi	1998/11/11 09:29:15
@@ -908,6 +908,11 @@
 @item MLOBJS
 A list of extra object files to link into any programs or libraries
 that you are building.
+
+ at item C2INITFLAGS and EXTRA_C2INITFLAGS
+Options to pass to the c2init program.
+(Note that compilation model options should be
+specified in @code{GRADEFLAGS}, not in @code{C2INITFLAGS}.)
 @end table
 
 Other variables also exist - see
@@ -2789,14 +2794,12 @@
 @menu
 * Tracing of Mercury programs::
 * Preparing a program for debugging::
+* Selecting trace events::
 * Mercury debugger invocation::
 * Mercury debugger concepts::
 * Debugger commands::
 @end menu
 
- at c XXX
-This chapter of the user's guide is still under construction.
-
 @node Tracing of Mercury programs
 @section Tracing of Mercury programs
 
@@ -2809,18 +2812,18 @@
 are
 
 @table @emph
- at item call events
+ at item call
 A call event occurs just after a procedure has been called,
 and control has just reached the start of the body of the procedure.
- at item exit events
+ at item exit
 An exit event occurs when a procedure call has succeeded,
 and control is about to return to its caller.
- at item redo events
+ at item redo
 A redo event occurs when all computations
 to the right of a procedure call have failed,
 and control is about to return to this call
 to try to find alternative solutions.
- at item fail events
+ at item fail
 A fail event occurs when a procedure call has run out of alternatives,
 and control is about to return to the rightmost computation to its left
 that still has possibly successful alternatives left.
@@ -2856,20 +2859,20 @@
 The internal event types are:
 
 @table @emph
- at item then events
+ at item then
 A then event occurs when execution reaches
 the start of the then part of an if-then-else.
 The path associated with the event specifies which if-then-else this is.
- at item else events
+ at item else
 An else event occurs when execution reaches
 the start of the else part of an if-then-else.
 The path associated with the event specifies which if-then-else this is.
- at item disj events
+ at item disj
 A disj event occurs when execution reaches
 the start of a disjunct in a disjunction.
 The path associated with the event specifies
 which disjunct of which disjunction this is.
- at item switch events
+ at item switch
 A switch event occurs when execution reaches
 the start of one arm of a switch
 (a disjunction in which each disjunct unifies a bound variable
@@ -2880,7 +2883,7 @@
 @c @item pragma_later
 @end table
 
-A path is a sequence of path components separated by semicolons,
+A path is a sequence of path components separated by semicolons.
 Each path component is one of the following:
 
 @table @code
@@ -2902,63 +2905,239 @@
 The goal inside an existential quantification.
 @end table
 
+A path describes the position of a goal
+inside the body of a procedure definition.
+For example, if the procedure body is a disjunction
+in which each disjunct is a conjunction,
+then the path ``d2;c3;'' denotes the third conjunct within the second disjunct.
+If the third conjunct within the second disjunct is an atomic goal
+such as a call or a unification,
+then this will be the only goal with whose path has ``d2;c3;'' as a prefix.
+If it is a compound goal,
+then its components will all have paths that have ``d2;c3;'' as a prefix,
+e.g. if it is an if-then-else,
+then its three components will have the paths
+``d2;c3;?;'' ``d2;c3;t;'' and ``d2;c3;e;''.
+
+Paths refer to the internal form of the procedure definition.
+When debugging is enabled (and the option --trace-optimized is not given),
+the compiler will try to keep this form
+as close as possible to the source form of the procedure,
+in order to make event paths as useful as possible to the programmer.
+Due to the compiler's flattening of terms,
+and its introduction of extra unifications to implement calls in implied modes,
+the number of conjuncts in a conjunction will frequently differ
+between the source and internal form of a procedure.
+This is rarely a problem, however, as long as you know about it.
+Mode reordering can be a bit more of a problem,
+but it can be avoided by writing single-mode predicates and functions
+so that producers come before consumers.
+The compiler transformation that
+potentially causes the most trouble in the interpretation of goal paths
+is the conversion of disjunctions into switches.
+In most cases, a disjunction is transformed into a single switch,
+and it is usually easy to guess, just from the events within a switch arm,
+just which disjunct the switch arm corresponds to.
+Some cases are more complex;
+for example, it is possible for a single disjunction
+can be transformed into several switches,
+possibly with other, smaller disjunctions inside them.
+In such cases, making sense of goal paths
+may require a look at the internal form of the procedure.
+You can ask the compiler to generate a file
+with the internal forms of the procedures in a given module
+by including the options ``-dfinal -Dpaths'' on the command line
+when compiling that module.
+
 @node Preparing a program for debugging
 @section Preparing a program for debugging
 
-Mercury debugging works by embedding calls to the debugging system
-into the executable code of Mercury procedures,
+When you compile a Mercury program, you can specify
+whether you want to be able to run the Mercury debugger on the program or not.
+If you do, the compiler embeds calls to the Mercury debugging system
+into the executable code of the program,
 at the execution points that represent trace events.
 At each event, the debugging system decides
-whether to give control to the user,
-who can then examine the state of the computation and issue commands,
-or whether to give control back to the executable.
-
- at c XXX
- at c Most programs include 
-
- at c XXX
- at c Programmers can control 
- at c The fewer events are to be traced
- at c the smaller the size of the executable
+whether to give control back to the executable immediately,
+or whether to first give control to you,
+allowing you to examine the state of the computation and issue commands.
+
+Mercury supports two broad ways of preparing a program for debugging.
+The simpler way is to compile a program in a debugging grade,
+which you can do directly by specifying a grade
+that includes the word ``debug'' (e.g. @samp{asm_fast.gc.debug}),
+or indirectly by specifying the @samp{--debug} grade option
+to the compiler, linker, c2init and other tools.
+If you follow this way,
+and accept the default settings of the various compiler options
+that control the selection of trace events (which are described below),
+you will be assured of being able to get control
+at every execution point that represents a potential trace event,
+which is very convenient.
+
+The two drawbacks of using a debugging grade,
+are the large size of the resulting executables,
+and the fact that often you discover that you need to debug a big program
+only after having built it in a non-debugging grade.
+This is why Mercury also supports another way
+to prepare a program for debugging,
+one that does not require the use of a debugging grade.
+With this way, you can decide, individually for each module,
+which of three trace levels, @samp{none}, @samp{shallow} and @samp{deep},
+you want to compile them with:
 
-Every module can be compiled with one of several trace levels.
-
- at table @emph
- at item trace level none
-A procedure compiled with trace level none
+ at table @samp
+ at item none
+A procedure compiled with trace level @samp{none}
 will never generate any events.
- at item trace level deep
-A procedure compiled with trace level deep
+ at item deep
+A procedure compiled with trace level @samp{deep}
 will always generate all the events requested by the user.
- at item trace level shallow
-A procedure compiled with trace level shallow
+XXX By default, this is all possible events,
+but you can tell the compiler that
+you are not interested in some kinds of events
+via compiler options (see below).
+ at item shallow
+A procedure compiled with trace level @samp{shallow}
 will generate interface events
-if it is called from a procedure compiled with trace level deep,
-but it will not generate any events
-if it is called from a procedure compiled with trace level shallow.
-Which way it will behave
-if it is called from a procedure compiled with trace level none
-depends on whether its nearest ancestor whose trace level is not none
-has trace level deep or shallow.
+if it is called from a procedure compiled with trace level @samp{deep},
+but it will never generate any internal events,
+and it will not generate any interface events either
+if it is called from a procedure compiled with trace level @samp{shallow}.
+If it is called from a procedure compiled with trace level @samp{none},
+the way it will behave is dictated by whether
+its nearest ancestor whose trace level is not @samp{none}
+has trace level @samp{deep} or @samp{shallow}.
+ at end table
+
+The intented use of these trace levels are as follows.
+
+ at table @emph
+ at item
+You should compile a module with trace level @samp{deep}
+if you suspect there may be a bug in the module,
+or if you think that being able to examine what happens inside that module
+can help you locate a bug.
+ at item
+You should compile a module with trace level @samp{shallow}
+if you believe the code of the module is reliable and unlikely to have bugs,
+but you still want to be able to get control at calls to and returns from
+any predicates and functions defined in the module,
+and if you want to be able to see the arguments of those calls.
+ at item
+You should compile a module with trace level @samp{none}
+only if you are reasonably confident that the module is reliable,
+and if you believe that knowing what calls other modules make to this module
+would not significantly benefit you in your debugging.
 @end table
 
- at c XXX explain --trace
- at c XXX --debug and not --debug
+In general, it is a good idea for most or all modules
+that can be called from modules compiled with trace level @samp{deep}
+to be compiled with at least trace level @samp{shallow}.
+
+You can control what trace level a module is compiled with
+by giving one of the following compiler options:
 
 @table @samp
- at item --trace minimum
-With --require-tracing, this sets the trace level to shallow;
-with --no-require-tracing, it sets the trace level to none.
 @item --trace shallow
-This always sets the trace level to shallow.
+This always sets the trace level to @samp{shallow}.
 @item --trace deep
-This always sets the trace level to deep.
+This always sets the trace level to @samp{deep}.
+ at item --trace minimum
+In debugging grades, this sets the trace level to @samp{shallow};
+in non-debugging grades, it sets the trace level to @samp{none}.
 @item --trace default
-With --require-tracing, this sets the trace level to deep;
-with --no-require-tracing, it sets the trace level to none.
+In debugging grades, this sets the trace level to @samp{deep};
+in non-debugging grades, it sets the trace level to @samp{none}.
 @end table
 
- at c XXX c2init -i
+As the name implies, the fourth alternative is the default,
+which is why by default you get
+no debugging capability in non-debugging grades
+and full debugging capability in debugging grades.
+The table also shows that in a debugging grade,
+no module can be compiled with trace level @samp{none}.
+
+A small but vital part of preparing an executable for debugging
+is the setup of the initialization file for debugging.
+The initialization file is created by the c2init command,
+which can be told to set up the initialization file for debugging
+in one of two ways.
+First, c2init accepts the same set of grade options the compiler accepts.
+If these options specify a debugging grade,
+c2init will set up the initialization file for debugging.
+Even if these options specify a non-debugging grade,
+you can ask c2init to set up the initialization file for debugging
+by giving it the @samp{-t} (for @emph{trace}) option.
+
+ at node Selecting trace events
+ at section Selecting trace events
+
+ at c XXX anybody got a better title for this section?
+
+In preparing a Mercury program for debugging,
+the Mercury compiler provides two options that you can use
+to say that you are not interested in certain kinds of events,
+and that the compiler should therefore not generate code for those events.
+This makes the executable smaller and faster.
+
+The first of these options is @samp{--no-trace-internal}.
+If you specify this when you compile a module,
+you will not get any internal events
+from predicates and functions defined in that module,
+even if the trace level is @samp{deep};
+you will only get external events.
+These are sufficient to tell you what a predicate or function does,
+i.e. what outputs it computes from what inputs.
+They do not tell you how it computed those outputs,
+i.e. what path control took through the predicate or function,
+but that is sometimes of no particular interest.
+In any case, much of the time you can deduce the path
+from the events that result from
+calls made by the predicate or function in question.
+
+The second of these options is @samp{--no-trace-redo},
+which can be specified independently of @samp{--no-trace-internal}.
+If you specify this when you compile a module,
+you will not get any redo events
+from predicates and functions defined in that module.
+If you are not interested in how backtracking arrives
+at a program point where forward execution can resume after a failure,
+this is an entirely reasonable thing to do.
+In any case, with sufficient thought and a memory of previous events
+you can reconstruct the sequence of redo events
+that would normally be present between the fail event
+and the event that represents the resumption of forward execution.
+This sequence has a redo event
+for every call to a procedure that can succeed more than once
+that occurred after the call to the procedure
+in which the resumption event occurs,
+provided that that call has not failed yet,
+and in reverse chronological order.
+
+Normally, when it compiles a module with a trace level other than @samp{none},
+the compiler will include in the module's object file
+information about all the call return sites in that module.
+This information allows the debugger to print stack dumps,
+as well as the values of variables in ancestors of current call.
+However, if you specify the @samp{--no-trace-return} option,
+the compiler will not include this information in the object file,
+reducing its size but losing the above functionality.
+
+ at c XXX should we document --stack-trace-higher-order
+ at c it has not really been tested yet
+
+By default, all trace levels other than @samp{none}
+turn off all compiler optimizations
+that can affect the sequence of trace events generated by the program,
+such as inlining.
+If you are specifically interested in
+how the compiler's optimizations affect the trace event sequence,
+you can specify the option @samp{--trace-optimized},
+which tells the compiler that it does not have to disable those optimizations.
+(A small number of low-level optimizations
+have not yet been enhanced to work properly in the presence of tracing,
+so compiler disables these even if @samp{--trace-optimized} is given.)
 
 @node Mercury debugger invocation
 @section Mercury debugger invocation
@@ -2966,17 +3145,35 @@
 The executables of Mercury programs
 by default do not invoke the Mercury debugger
 even if some or all of their modules were compiled with some form of tracing,
-and even if the grade of the executable includes @code{debug}.
+and even if the grade of the executable is a debugging grade,
 This is similar to the behavior of executables
 created by the implementations of other languages;
 for example the executable of a C program compiled with -g
 does not autonomously invoke gdb or dbx etc when it is executed.
 
+Unlike those other language implementations,
+when you invoke the Mercury debugger @samp{mdb},
+you invoke it not just with the name of an executable
+but with the command line you want to debug.
+If something goes wrong when you execute the command
+
 @example
-mdb @var{prog} @var{arg1} ...
+ at var{prog} @var{arg1} @var{arg2} ...
 @end example
 
+and you want to find the cause of the problem,
+you must execute the command
+
+ at example
+mdb @var{prog} @var{arg1} @var{arg2} ...
+ at end example
+
+because you do not get a chance
+to specify the command line of the program later.
+
 @c XXX more to come
+ at c environment variables controlling debugger startup
+ at c sourcing of .mdbrc files
 
 @node Mercury debugger concepts
 @section Mercury debugger concepts
@@ -3113,7 +3310,7 @@
 Some commands take a number as their first parameter.
 For such commands, users can type `@var{number} @var{command}'
 as well as `@var{command} @var{number}'.
-The debugger will internally transform the former into the latter,
+The debugger will treat the former as the latter,
 even if the number and the command are not separated by white space.
 
 @menu
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/exceptions
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/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
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing trial
cvs diff: Diffing util



More information about the developers mailing list