[m-rev.] for post-commit review: fill in most of the grade modifiers section
Julien Fischer
jfischer at opturion.com
Fri Aug 8 16:04:51 AEST 2025
On Thu, 7 Aug 2025 at 15:14, Zoltan Somogyi <zoltan.somogyi at runbox.com> wrote:
>
> diff --git a/doc/user_guide.texi b/doc/user_guide.texi
> index 64bdd9678..98eb0e893 100644
> --- a/doc/user_guide.texi
> +++ b/doc/user_guide.texi
...
> @@ -992,12 +998,526 @@ as these are the two fastest.
> @node Grade modifiers
> @section Grade modifiers
>
> +The available grade modifiers
> +each belong to a small group of grade modifiers
> +that all govern the same aspect of compilation.
That's a bit awkward. I suggest:
Every grade modifier belongs to a @dfn{grade modifier group}.
Each grade modifier group governs a single aspect of compilation.
> +Because each modifier calls for handling that aspect
> +differently from what the other modifiers in the group call for,
s/in the group/in its group/
> +a grade may contain at most one modifier from each group.
> +Note also that
> + at itemize
> + at item
> +some grade modifiers are compatible
> +only with some base grades (usually the ones that target C) and not others; and
> + at item
> +some grade modifiers in one group
> +are incompatible not just with all other grade modifiers in the same group,
> +but also with some grade modifiers from other groups.
> + at end itemize
> +
> +Note also that the Mercury standard library
> +will have been installed on your system
> +in only a subset of the set of all possible grades.
> +
> +Each of the following subsections except the last
> +documents one group of grade modifiers.
> +The last subsection documents which grade modifiers
> +are compatible with grade modifiers from other groups.
> +
> + at menu
> +* Grade modifiers for debugging Mercury programs::
> +* Grade modifiers for profiling Mercury programs::
> +* Grade modifiers for trailing::
> +* Grade modifiers for minimal model tabling::
> +* Grade modifiers for parallelism::
> +* Grade modifiers for flexible stack sizes::
> +* Grade modifiers for garbage collection::
> +* Grade modifiers for single precision floats::
> +* Grade modifiers for C debugging::
> +* Compatibility of grade modifiers::
> + at end menu
> +
> + at c NODOC We do not document .pregen
Maybe we need to say something about, given that users will see it when they
install Mercury?
> + at c NODOC We do not document .rbmm*
> +
> + at c ----------------------------------------------------------------------------
> +
> + at node Grade modifiers for debugging Mercury programs
> + at subsection Grade modifiers for debugging Mercury programs
> +
> +In the absence of both of the grade modifiers in this group,
> +the Mercury compiler generates executables that cannot be debugged,
> +because they do not include the information needed
> +for the operation of the Mercury debugger,
> +whose name is @command{mdb} @ref{Debugging}.
> +
> + at table @code
> + at item .debug
> + at item .decldebug
> +Compiling programs in a grade that includes
> +either @code{.debug} or the @code{.decldebug} grade modifier
Add "the" before @code{.debug}.
> +generates executables that can be debugged using @command{mdb}.
> +Invoking @command{mdb} on such executables allows users to do
s/allows users to do/lets users do/
> +the kinds of things that people do with C debuggers such as @command{gdb}
> +(set breakpoints, step forward e.g. one call at a time,
> +and print the values of variables, amongst others),
> +as well as the kinds of things that people do with debug mode in Prolog:
> +(such as jump back from the end of a call to its beginning).
> +The difference between them is that
> +the declarative debugging aspects of @samp{mdb}
> +will work only with @samp{.decldebug}.
> +While both @code{.debug} and @code{.decldebug}
> +increase the size of the executable and reduce its speed,
> +both the size increase and the speed reduction
> +is larger with @code{.decldebug} than with @code{.debug}.
> + at sp 1
> +Both of these grade modifiers are compatible only with LLDS base grades.
> + at end table
> +
> + at c NODOC We do not document ssdebug.
> +
> + at c ----------------------------------------------------------------------------
> +
> + at node Grade modifiers for profiling Mercury programs
> + at subsection Grade modifiers for profiling Mercury programs
> +
> +In the absence of all of the grade modifiers in this group,
> +the Mercury compiler generates executables that cannot be profiled.
> +Mercury actually supports two completely separate profilers:
> + at command{mprof} and @command{mdprof}.
> +
> + at command{mprof} is effectively a Mercury clone
> +of one of the standard profilers for C, namely @command{gprof}.
> +Like many (if not most) profilers,
> +it operates by recording what part of the program was executing
> +when its process is sent a periodic profiling signal by the OS.
> +Like @command{gprof}, at each profiling signal,
> +it records what predicate it was executing at the time
> +and where it was called from, but no more than that.
> +
> +This works well for C, where each function typically has one job,
> +but not for Mercury, which has many polymorphic predicates
> +that can be used in the implementation of many different jobs,
> +with many different performance behaviors.
> +This is why Mercury also has @command{mdprof},
> +the Mercury @emph{deep} profiler,
> +which at each profiling signal records the identity
> +of not just the immediate parent of the currently executing predicate,
> +but effectively the identities of @emph{all} its other ancestors as well.
> +(This is the ``deep context'' after which the profiler is named.)
> +
> +The two profilers operate differently
> +and have different strengths and weaknesses.
> +You can read more about both of them in @ref{Profiling}.
> +
> + at table @code
> + at item .prof
> +Compiling programs in a grade that includes the @code{.prof} grade modifier
> +generates executables that, when executed,
> +generate files containing information that @command{mprof},
> +the @command{gprof}-style profiler,
> +can use to tell you where the program is spending its time.
> + at sp 1
> +This grade modifier is compatible only with base grades that target C.
> + at item .memprof
> +Compiling programs in a grade that includes the @code{.memprof} grade modifier
> +generates executables that, when executed,
> +generate files containing information that @command{mprof},
> +the @command{gprof}-style profiler,
> +can use to tell you where the program is allocating memory.
> + at sp 1
> +This grade modifier is compatible only with base grades that target C.
> + at item .profdeep
> +Compiling programs in a grade that includes the @code{.profdeep} grade modifier
> +generates executables that, when executed,
> +generate files containing information that @command{mdprof},
> +the Mercury deep profiler, can use to tell you
> +both where the program is spending its time and where it is allocating memory.
> + at sp 1
> +This grade modifier is compatible only with LLDS base grades
> +(which all target C).
> + at end table
> +
> + at c NODOC We do not document .proftime, .profcalls, and .profall
> +
> + at c NODOC We do not document Threadscope (here, but we do elsewhere?).
> +
> + at c NODOC We do not document term size profiling.
> +
> + at c ----------------------------------------------------------------------------
> +
> + at node Grade modifiers for trailing
> + at subsection Grade modifiers for trailing
> +
> +In the absence of the @code{.tr} grade modifier,
> +the Mercury compiler generates executables that do not support trailing.
> +
> +Trailing is a technique that
> +the implementations of logic programming languages use
> +to support constraint solving.
> +All Prolog implementations use it,
> +because unification in standard Prolog is effectively a solver
> +for constraints of the form ``are these two terms unifiable?''.
> +(Such constraints are usually called @dfn{Herbrand} constraints.)
> +In Mercury, the mode system imposes a requirement that
> +when two terms are unified, one of them must be ground,
> +which means that such questions are always trivially answerable.
> +In fact, the design of Mercury was driven in large part by the intention
> +to @emph{avoid} any requirement for constraint solving,
> +because they make programs harder to understand
s/they make/it makes/
> +both by humans, and by the compiler.
> +Unlike Prolog, Mercury thus has no constraint solver built into it.
> +However, Mercury @emph{can} be used to @emph{implement} constraint solvers.
> +While the act of posting a constraint in such a program is a declarative action,
> +its implementation requires updating a constraint store.
> +This in turn requires that when execution backtracks
> +past the goal that posted the constraint,
> +the update to the constraint store must be undone.
> +
> +This is why in the right grades, mercury can support a trail.
s/mercury/Mercury/
> +The trail is a stack-like data structure
> +that consists of a sequence of entries,
> +each of which effectively describes how to undo an update to a data structure.
> +This can be used to implement constraint solvers like this:
> +
> + at itemize @bullet
> + at item
> +When execution is about to enter a disjunction or an if-then-else,
> +the implementation records the address of the top of the trail,
> +effectively as a snapshot.
> + at item
> +When the program adds a new constraint to the constraint store,
> +it must also push a new entry on top of the trail that describes
> +how to undo the addition of this new constraint.
> +(That entry will consist of the address of the undo function,
> +and an argument for it that identifies the specific addition to undo.)
> + at item
> +Whenever execution backtracks,
> +either to a later disjunct in a disjunction
> +or to the else part of an if-then-else,
> +the implementation walks the trail
> +from the current top of the trail down to the snapshot address
> +that was recorded on entry to the current disjunction or if-then-else,
> +and executes the undo actions that they encode.
> +This is usually called @emph{unwinding} the trail.
> + at end itemize
> +
> + at table @code
> + at item .tr
> +Compiling programs in a grade that includes the @code{.tr} grade modifier
> +generates executables that support trailing.
> +This means that the compiler-generated code
> +will create the snapshots and unwind the trail as needed.
> + at c The part in between,
> +The addition of new constraints to the constraint store,
> +and the addition of new entries to the trail to undo those additions,
> +will be done by C code in @code{foreign_proc} pragmas written by the user.
> +(Each trail entry consists of the address of a C function to call,
> +and an argument to invoke that function with.)
> +
> +This grade modifier is compatible only with base grades that target C.
> +Each trail entry consists of the address of a C function to call,
> +and an argument to invoke that function with.
That's true for function trailing, not value trailing. I suggest deleting
that last sentence and instead pointing users to the Trailing section of
the reference manual.
> + at end table
> +
> + at c ----------------------------------------------------------------------------
> +
> + at node Grade modifiers for parallelism
> + at subsection Grade modifiers for parallelism
> +
> ZZZ TODO
>
> - at sp 1
> -Note that not all combinations of components are allowed, and that the
> -Mercury standard library will have been installed on your system in
> -only a subset of the set of all possible grades.
> + at c ----------------------------------------------------------------------------
> +
> + at node Grade modifiers for minimal model tabling
> + at subsection Grade modifiers for minimal model tabling
> +
> +Mercury supports several forms of tabling,
> +most of which must be explicit enabled
> +for each procedure that are intended to apply to.
> +(Recall that a @dfn{procedure} is one mode of a predicate or function.)
> +Tabling operates by recording (in a table, hence the name),
> +for each vector of input values to a procedure,
> +the set of vectors of output values the procedure returns as results.
> +(For @code{det} code, the set will contain exactly one vector;
> +for @code{semidet} code, the set will contain at most one vector.)
> +For later calls to a tabled procedure,
> +the Mercury implementation will automatically check whether
> +the current vector of values of the input arguments has occurred before.
> +If it has, it will return the recorded set of answers.
> +If it has not, it will compute the result or results, and record it or them.
> +
> +This system has a problem if the tabled procedure calls itself recursively,
> +either directly or indirectly,
> +with the exact same vector of input values,
> + at emph{before} its initial invocation has completed,
> +because in that case,
> +there will be an entry recording the input vector,
> +but the corresponding set of output value vectors will not yet be available.
> +With the most frequently used form of tabling, i.e. @emph{memoization},
> +this is a fatal error,
> +and the Mercury implementation will automatically abort the program.
> +However, for @code{nondet} predicates, there is a way to avoid this abort,
> +at the cost of a much more complicated execution model.
> +
> +This solution gets its name, @dfn{minimal model tabling},
> +from the fact that it is intented to return,
s/intented/intended/
> +for each query, all the answers that match that query
> +in the @dfn{minimal model} of the program.
> + at c ZZZ I can't find a good wikipedia reference
> +It consists of
> +
> + at itemize
> + at item
> +recording that state of the computation at the point of the recursive call;
> + at item
> +continuing execution as if the call failed;
> + at item
> +when the top-level call to the procedure
> +with the given vector of input argument values
> +finds a new solution,
> + at emph{restoring} the recorded state of the computation,
> +and restarting its execution, but this time behaving
> +as if the recursive call just returned the new solution.
> + at item
> +This restarted execution may obviously return even more solutions,
> +which have to be fed back to the recursive call
> +(or in the general, the recursive calls, plural).
> +The process ends when all restarted calls lead
> +either to no solution, or to solutions that have all previously been
> +not just recorded, but also fed back to all recursive call sites.
> + at end itemize
> +
> +The execution mechanisms required for this are quite complicated,
> +and impose significant overheads in both time and space,
> +even on the parts of the program that do not benefit from it.
> +This is why in the absence of the following grade modifiers,
> +the Mercury compiler generates executables
> +that do not support minimal model tabling.
> +
> + at table @code
> + at item .mm
> +Compiling programs in a grade that includes the @code{.mm} grade modifier
> +generates executables that support minimal model tabling.
> +
> +This grade modifier is compatible only with LLDS base grades.
> + at item .mmsc
> +The grade modifier @samp{.mmsc} is a synonym for @samp{.mm},
> +standing for ``minimal model via stack copying'',
> +since the standard implementation works by copying parts of the stack.
> +The synonym exists because Mercury also has
> +another implementation of minimal model tabling.
> +This other implementation, which is incomplete
> +and was only ever useful for experiments,
> +is based on a completely different implementation technique.
> + at end table
There should be a pointer to the "Tabled evaluation" section of the reference
manual somewhere in that section.
> +
> + at c ----------------------------------------------------------------------------
> +
> + at node Grade modifiers for flexible stack sizes
> + at subsection Grade modifiers for flexible stack sizes
> +
> +In MLDS grades, the code generated by the Mercury compiler
> +uses the native call stack of the target language.
> +In LLDS grades, on the other hand,
> +the generated code manages its own two stacks:
> +the @dfn{det stack}, which stores the data
> +of procedures that @emph{cannot} succeed more than once,
> +and the @dfn{nondet stack}, which stores the data
> +of procedures that @emph{can} succeed more than once.
> +(The two stacks are separate because
> +for predicates that can succeed more than once, we cannot throw away
> +the values of their input arguments and local variables when they succeed,
> +while for predicates that cannot succeed more than once,
> +we can throw them away, and for good performance, we @emph{must} do so.)
> +
> +By default, Mercury reserves a fixed size block of memory for each stack,
> +and never increases their size during execution.
> +To make this work even for programs that use relatively deep recursion,
> +the default size of the det stack is
> +16 megabytes on 32-bit machines, and 32 megabytes on 64-bit machines.
> +These default sizes can be overridden using runtime options,
Add a pointer to "Environment variables affecting the Mercury runtime system"
section here.
> +but whatever pair of sizes one picks,
> +for some programs, they will be wasteful overkill,
> +while for some other programs, hopefully rarely,
> +they nevertheless will not be enough.
> +If the platform allows it, we make the top page of each stack inaccessible,
> +so that a stack overflow,
> +instead of accessing and overwriting memory effectively randomly,
> +causes the operating system to send a signal to the program.
> +If not caught and handled,
> +this signal will abort the program, minimizing the damage.
> +
> + at c Each frame on the det stack contains
> + at c a pointer to the stack frame just below it,
> + at c the values of the input arguments and local variables of a call,
> + at c and the return address to which the call will jump when done.
> + at c Each frame on the nondet stack is similar,
> + at c but it contains more information to manage the distinct actions
> + at c that such procedures should take on success and on failure.
> +
> +We therefore have a grade modifier
> +that makes the sizes of the two stacks dynamic,
> +and able to respond to the actual requirements of the program being executed.
> +
> + at table @code
> + at item .stseg
> +Compiling programs in a grade that includes the @code{.stseg} grade modifier
> +generates executables that use @dfn{stack segments},
> +small memory areas whose size is 16 or 32 kilobytes
> +on 32- and 64-bit systems respectively.
> +In @code{.stseg} grades, the det and nondet stacks
> +both consist of a linked list of one or more stack segments.
> +Each stack grows by adding a new segment at a time on demand,
> +and shrinks by putting segments back on a free list
> +once they are no longer needed.
> +
> +Using stack segments does have a small performance penalty,
> +because it requires code for checking
> + at itemize @bullet
> + at item
> +whether the creation of a new stack frame
> +requires the allocation of a new stack segment
> +and adding it to the linked list, and
> + at item
> +whether a stack frame being popped off the stack
> +was the last frame in its segment,
> +allowing the segment to be removed from the stack's linked list,
> +and made available for future allocations.
> + at end itemize
> +However, for many applications,
> +this is a more than acceptable price to pay
> +for not imposing any limit on stack sizes
> +other than the amount of available memory.
> +
> +This grade modifier is relevant only for LLDS base grades,
> +and is compatible only with them.
> + at end table
...
> + at node Grade modifiers for garbage collection
> + at subsection Grade modifiers for garbage collection
> +
> +By default, the Mercury system provides no garbage collection
> +beyond what the target language provides.
> +C# and Java have their own builtin garbage collectors, but C does not.
> +Since garbage collection is essential for all programs
> +other than those with @emph{very} short runtimes,
> +base grades that target C usually include a grade modifier
> +that specifies which garbage collector to use.
> +
> + at table @code
> + at item .gc
> +Compiling programs in a grade that includes the @code{.gc} grade modifier
> +generates executables that use the standard Mercury garbage collector,
> +which is the Boehm-Demers-Weiser conservative collector for C.
> +
> +This grade modifier is relevant only for LLDS base grades,
> +and is compatible only with them.
No, it's also relevant for the MLDS C grades.
Julien.
More information about the reviews
mailing list