Copyright (C) 1995 University of Melbourne.
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
This document describes the compilation environment of Mercury. It describes how to use `mc', the Mercury compiler; how to use `mmake', the "Mercury make" program, a tool built on top of ordinary or GNU make to simplify the handling of Mercury programs; and how to use Prolog to debug Mercury programs.
We strongly recommend that programmers use `mmake' rather than invoking `mc' directly, because `mmake' is generally easier to use and avoids unnecessary recompilation.
Since the Mercury implementation is essentially a native-code compiler which happens to compile via GNU C, not an interpreter, debugging of compiled Mercury programs would require a dedicated Mercury debugger program - or at least some significant extensions to gdb. It would also require the Mercury compiler to arrange for the object code to contain suitable debugging information. Although it is possible to debug the intermediate C code, this is not productive, since the intermediate C code is extremely low-level and bears little resemblance to the source code. As an alternative, Mercury programmers may wish to use a Prolog system to execute their Mercury programs in order to gain access to this facility. The feasibility of this technique is dependent upon the program being written in the intersection of the Prolog and Mercury languages, which is possible because the two languages have almost the same syntax. The Mercury implementation allows you to run a Mercury program using NU-Prolog or SICStus Prolog (see section Using Prolog).
Mercury source files should be named `*.m'. Each Mercury source file must contain a single Mercury module whose name should be the same as the filename without the `.m' extension.
Files ending in `.int', `.int2' and `.int3' are interface files; these are generated automatically by the compiler, using the `--make-interface' and `--make-short-interface' options. Files ending in `.opt' are interface files used in inter-module optimization, and are created using the `--make-optimization-interface' option.
Since the interface of a module changes less often than its implementation, the `.int', `.int2', `.int3', and `.opt' files will remain unchanged on many compilations. To avoid unnecessary recompilations of the clients of the module, the timestamps on the these files are updated only if their contents change. `.date', `.date3' and `.optdate' files associated with the module are used as date stamps; they are used when deciding whether the interface files need to be regenerated.
Files ending in `.d' are automatically-generated Makefile fragments which contain the dependencies for a module. Files ending in `.dep' are automatically-generated Makefile fragments which contain the rules for an entire program.
In the source code for the Mercury runtime library, we use a few files ending in `.mod'; these are preprocessed using the perl script `mod2c' to produce C files. (Originally the Mercury compiler also produced `.mod' files, but now we compile directly to C.)
As usual, `.c' files are C source code, `.h' files are C header files, `.o' files are object code, `.no' files are NU-Prolog object code, and `.ql' files are SICStus Prolog object code.
Following a long Unix tradition, the Mercury compiler is called `mc'. Some of its options (e.g. `-c', `-o', and `-I') have a similar meaning to that in other Unix compilers.
Arguments to `mc' that name Mercury source files may omit the `.m' suffix.
To compile a program which consists of just a single module, use the command
mc module.m
Unlike traditional Unix compilers, however, `mc' will put the executable into a file called `module', not `a.out'.
For programs that consist of more than one module, we recommend that you use Mmake (see section Using Mmake). Mmake will perform all the steps listed below, using automatic dependency analysis to ensure that things are done in the right order, and that steps are not repeated unnecessarily.
To compile a module to object code without creating an executable, use the command
mc -c module.m
`mc' will put the object code into a file called `module.o'. It also will leave the intermediate C code in a file called `module.c'.
Before you can compile a module, you must make the interface files for the modules that it imports (directly or indirectly). You can create the interface files for one or more modules using the commands
mc --make-short-interface module1.m module2.m ... mc --make-interface module1.m module2.m ...
If you are going to compile with `--intermodule-optimization' enabled, then you also need to create the optimization interface files.
mc --make-optimization-interface module1.m module2.m ...
Given that you have made all the interface files, one way to create an executable for a multi-module program is to compile all the modules at the same time using the command
mc module1.m module2.m ...
This will by default put the resulting executable in `module1', but you can use the `-o filename' option to specify a different name for the output file, if you so desire.
The other way to create an executable for a multi-module program is to compile each module separately using `mc -c', and then link the resulting object files together. The linking is a two stage process.
First, you must create and compile an initialization file, which is a C source file containing calls to automatically generated initialization functions contained in the C code of the modules of the program:
c2init module1.c module2.c ... > main_module_init.c, mgnuc -c main_module_init.c
The `c2init' command line must contain the name of the C file of every module in the program. The order of the arguments is not important. The `mgnuc' command is the Mercury GNU C compiler; it is a shell script that invokes the GNU C compiler `gcc' with the options appropriate for compiling the C programs generated by Mercury.
You then link the object code of each module with the object code of the initialization file to yield the executable:
ml -o main_module module1.o module2.o ... main_module_init.o
`ml', the Mercury linker, is another shell script that invokes a C compiler with options appropriate for Mercury, this time for linking. `ml' also pipes any error messages from the linker through `mdemangle', the Mercury symbol demangler, so that error messages refer to predicate and function names from the Mercury source code rather than to the names used in the intermediate C code.
The above command puts the executable in the file `main_module'. The same command line without the `-o' option would put the executable into the file `a.out'.
`mc' and `ml' both accept a `-v' (verbose) option. You can use that option to see what is actually going on. For the full set of options of `mc', see section Invocation.
Once you have created an executable for a Mercury program, you can go ahead and execute it. You may however wish to specify certain options to the Mercury runtime system. The Mercury runtime accepts options via the `MERCURY_OPTIONS' environment variable. Setting `MERCURY_OPTIONS' to `-h' will list the available options. The most useful of these are the options that set the size of the stacks.
The det stack and the nondet stack are allocated fixed sizes at program start-up. The default size is 512k for the det stack and 128k for the nondet stack, but these can be overridden with the `-sd' and `-sn' options, whose arguments are the desired sizes of the det and nondet stacks respectively, in units of kilobytes. On operating systems that provide the appropriate support, the Mercury runtime will ensure that stack overflow is trapped by the virtual memory system.
With conservative garbage collection (the default), the heap will start out with a zero size, and will be dynamically expanded as needed, When not using conservative garbage collection, the heap has a fixed size like the stacks. The default size is 4 Mb, but this can be overridden with the `-sh' option.
Since the current Mercury implementation does not yet provide any useful support for debugging, we recommend that you use a Prolog system for debugging your Mercury programs. However, there is no point in using a Prolog debugger to track down a bug that can be detected statically by the Mercury compiler. The command
mc -e module1.m ...
causes the Mercury compiler to perform all its syntactic and semantic checks on the named modules, but not to generate any code.
In our experience, omitting that step is not wise. If you do omit it, you often waste a lot of time debugging problems that the compiler could have detected for you.
You can compile a Mercury source module using NU-Prolog via the command
mnc module1.m ...
`mnc' is the Mercury variant of `nc', the NU-Prolog compiler.
It adapts nc
to compile Mercury programs,
e.g. by defining do-nothing predicates for the various Mercury declarations
(which are executed by nc
).
Some invocations of `mnc' will result in warnings such as
Warning: main is a system predicate. It shouldn't be used as a non-terminal.
Such warnings should be ignored.
`mnc' compiles the modules it is given into NU-Prolog bytecode, stored in files with a `.no' suffix. You can link these together using the command
mnl -o main_module module1.no ...
Ignore any warnings such as
Warning: main/2 redefined Warning: solutions/2 redefined Warning: !/0 redefined
`mnl', the Mercury NU-Prolog linker, will put the executable (actually a shell script invoking a save file) into the file `main_module.nu'. This can be executed normally using
./main_module.nu arguments
Alternatively, one can execute such programs using `mnp', the Mercury version of np, the NU-Prolog interpreter. The command
mnp
will start up the Mercury NU-Prolog interpreter. Inside the interpreter, you can load your source files with a normal consulting command such as
['module.m'].
You can also use the `--debug' option to `mnl' when linking. This will produce an executable whose entry point is the NU-Prolog interpreter, rather than main/2 in your program.
In both cases, you can start executing your program by typing
r("program-name arguments").
at the prompt of the NU-Prolog interpreter.
All the NU-Prolog debugging commands work as usual.
The most useful ones are
the trace
and spy
commands at the main prompt
to turn on complete or selective tracing respectively,
and the l
(leap), s
(skip), and r
(redo)
commands of the tracer.
For more information, see the NU-Prolog documentation.
By default the debugger only displays the top levels of terms;
you can use the `|' command to enter an interactive term browser.
(Within the term browser, type `h.' for help.)
Also note that in the debugger, we use a version of error/1
which fails rather than aborting after printing the "Software Error:" message.
This makes debugging easier,
but will of course change the behaviour after an error occurs.
Using SICStus Prolog is similar to using NU-Prolog, except that the commands to use are `msc', `msl', and `msp' rather than `mnc', `mnl', and `mnp'.
Due to shortcomings in SICStus Prolog (in particular, the lack of backslash escapes in character strings), you need to use `sicstus_conv' to convert Mercury `.m' files to the `.pl' files that SICStus Prolog expects before you can load them into the interpreter. The command to use is just
sicstus_conv module.m
By default, `msc' compiles files to machine code using
SICStus Prolog's `fastcode' mode. If space is more important
than speed, you can use the `--mode compactcode' option,
which instructs msc
to use SICStus Prolog's `compactcode'
mode, which compiles files to a bytecode format.
There are some Mercury programs which are not valid Prolog programs. In particular, Mercury will always reorder goals to ensure that they are mode-correct (or report a mode error if it cannot do so), but Prolog systems will not always do so, and will sometimes just silently give the wrong result. For example, in Mercury the following predicate will usually succeed, whereas in Prolog it will always fail.
:- pred p(list(int)::in, list(int)::out) is semidet. p(L0, L) :- L \= [], q(L0, L). :- pred q(list(int)::in, list(int)::out) is det.
The reason is that in Mercury,
the test `L \= []' is reordered to after the call to q/2
,
but in Prolog, it executes even though L
is not bound,
and consequently the test always fails.
NU-Prolog has logical alternatives to the non-logical Prolog operations, and since Mercury supports both syntaxes, you can use NU-Prolog's logical alternatives to avoid this problem. However, during the development of the Mercury compiler we had to abandon their use for efficiency reasons.
Another hazard is that NU-Prolog does not have a garbage collector.
Mmake, short for "Mercury Make", is a tool for building Mercury programs that is built on top of ordinary or GNU Make (1). With Mmake, building even a complicated Mercury program consisting of a number of modules is as simple as
mmake main-module.depend mmake main-module
Mmake only recompiles those files that need to be recompiled, based on automatically generated dependency information. Most of the dependencies are stored in `.d' files that are automatically recomputed every time you recompile, so they are never out-of-date. A little bit of the dependency information is stored in `.dep' files which are more expensive to recompute. The `mmake main-module.depend' command which recreates the `main-module.dep' file needs to be repeated only when you add or remove a module from your program, and there is no danger of getting an inconsistent executable if you forget this step -- instead you will get a compile or link error.
`mmake' allows you to build more than one program in the same directory. Each program must have its own `.dep' file, and therefore you must run `mmake program.depend' for each program.
If there is a file called `Mmake' in the current directory, Mmake will include that file in its automatically-generated Makefile. The `Mmake' file can override the default values of various variables used by Mmake's builtin rules, or it can add additional rules, dependencies, and actions.
Mmake's builtin rules are defined by the file `prefix/lib/mercury/mmake/Mmake.rules' (where prefix is `/usr/local/mercury-version' by default, and version is the version number, e.g. `0.6'), as well as the rules in the automatically-generated `.dep' files. These rules define the following targets:
The variables used by the builtin rules are defined in `prefix/lib/mercury/mmake/Mmake.vars'.
Note that since Mmake is built on top of Make or GNU Make, you can make use of the features supported by the underlying Make. In particular, GNU Make has support for running jobs in parallel, which is very useful if you have a machine with more than one CPU.
The Mercury profiler `mprof' is a tool which can be used to analyze a Mercury program's performance, so that the programmer can determine which predicates or functions are taking up a disproportionate amount of the execution time.
To obtain the best trade-off between productivity and efficiency, programmers should not spend too much time optimizing their code until they know which parts of the code are really taking up most of the time. Only once the code has been profiled should the programmer consider making optimizations that would improve efficiency at the expense of readability or ease of maintenance.
A good profiler is a tool that should be part of every software engineer's toolkit.
To enable profiling, your program must be built in a `.prof' grade. For example, if the default grade on your system is `asm_fast.gc', then to compile with profiling enabled, use grade `asm_fast.gc.prof'. You can do this by setting the `GRADE' variable in your Mmake file, e.g. by adding the line `GRADE=asm_fast.gc.prof'. See section Compilation model options for more information about the different grades.
Enabling profiling has several effects. Firstly, it causes the compiler to generate slightly modified code which counts the number of times each predicate or function is called, and for every call, records the caller and callee. Secondly, your program will be linked with versions of the library and runtime that were compiled with profiling enabled. (It also has the effect for each source file the compiler generates the static call graph for that file in `module.prof'.)
The next step is to run your program. The profiling version of your program will collect profiling information during execution, and save this information in the files `Prof.Counts', `Prof.Decls', and `Prof.CallPair'. (`Prof.Decl' contains the names of the procedures and their associated addresses, `Prof.CallPair' records the number of times each procedure was called by each different caller, and `Prof.Counts' records the number of times that execution was in each procedure when a profiling interrupt occurred.)
It would be nice if there was a way to combine profiling data from multiple runs of the same program, but unfortunately there is not yet any way to do that.
Due to a known timing-related bug in our code, you may occasionally get segmentation violations when running your program with profiling enabled. If this happens, just run it again -- the problem does not occur frequently. This bug will hopefully be fixed soon.
To display the profile, just type `mprof'. This will read the `Prof.*' files and display the flat profile in a nice human-readable format. If you also want to see the call graph profile, which takes a lot longer to generate, type `mprof -c'.
Note that `mprof' can take quite a while to execute, and will usually produce quite a lot of output, so you will usually want to redirect the output into a file with a command such as `mprof > mprof.out'.
The profile output consists of three major sections. These are named the call graph profile, the flat profile and the alphabetic listing.
The call graph profile presents the local call graph of each procedure. For each procedure it shows the parents (callers) and children (callees) of that procedure, and shows the execution time and call counts for each parent and child. It is sorted on the total amount of time spent in the procedure and all of its descendents (i.e. all of the procedures that it calls, directly or indirectly.)
The flat profile presents the just execution time spent in each procedure. It does not count the time spent in descendents of a procedure.
The alphabetic listing just lists the procedures in alphabetical order, along with their index number in the call graph profile, so that you can quickly find the entry for a particular procedure in the call graph profile.
The profiler works by interrupting the program at frequent intervals, and each time recording the currently active procedure and its caller. It uses these counts to determine the proportion of the total time spent in each procedure. This means that the figures calculated for these times are only a statistical approximation to the real values, and so they should be treated with some caution.
The time spent in a procedure and its descendents is calculated by propagating the times up the call graph, assuming that each call to a procedure from a particular caller takes the same amount of time. This assumption is usually reasonable, but again the results should be treated with caution.
Note that any time spent in a C function (e.g. time spent in `GC_malloc()', which does memory allocation and garbage collection) is credited to the Mercury procedure that called that C function.
Here is a small portion of the call graph profile from an example program.
called/total parents index %time self descendents called+self name index called/total children <spontaneous> [1] 100.0 0.00 0.75 0 call_engine_label [1] 0.00 0.75 1/1 do_interpreter [3] ----------------------------------------------- 0.00 0.75 1/1 do_interpreter [3] [2] 100.0 0.00 0.75 1 io__run/0(0) [2] 0.00 0.00 1/1 io__init_state/2(0) [11] 0.00 0.74 1/1 main/2(0) [4] ----------------------------------------------- 0.00 0.75 1/1 call_engine_label [1] [3] 100.0 0.00 0.75 1 do_interpreter [3] 0.00 0.75 1/1 io__run/0(0) [2] ----------------------------------------------- 0.00 0.74 1/1 io__run/0(0) [2] [4] 99.9 0.00 0.74 1 main/2(0) [4] 0.00 0.74 1/1 sort/2(0) [5] 0.00 0.00 1/1 print_list/3(0) [16] 0.00 0.00 1/10 io__write_string/3(0) [18] ----------------------------------------------- 0.00 0.74 1/1 main/2(0) [4] [5] 99.9 0.00 0.74 1 sort/2(0) [5] 0.05 0.65 1/1 list__perm/2(0) [6] 0.00 0.09 40320/40320 sorted/1(0) [10] ----------------------------------------------- 8 list__perm/2(0) [6] 0.05 0.65 1/1 sort/2(0) [5] [6] 86.6 0.05 0.65 1+8 list__perm/2(0) [6] 0.00 0.60 5914/5914 list__insert/3(2) [7] 8 list__perm/2(0) [6] ----------------------------------------------- 0.00 0.60 5914/5914 list__perm/2(0) [6] [7] 80.0 0.00 0.60 5914 list__insert/3(2) [7] 0.60 0.60 5914/5914 list__delete/3(3) [8] ----------------------------------------------- 40319 list__delete/3(3) [8] 0.60 0.60 5914/5914 list__insert/3(2) [7] [8] 80.0 0.60 0.60 5914+40319 list__delete/3(3) [8] 40319 list__delete/3(3) [8] ----------------------------------------------- 0.00 0.00 3/69283 tree234__set/4(0) [15] 0.09 0.09 69280/69283 sorted/1(0) [10] [9] 13.3 0.10 0.10 69283 compare/3(0) [9] 0.00 0.00 3/3 __Compare___io__stream/0(0) [20] 0.00 0.00 69280/69280 builtin_compare_int/3(0) [27] ----------------------------------------------- 0.00 0.09 40320/40320 sort/2(0) [5] [10] 13.3 0.00 0.09 40320 sorted/1(0) [10] 0.09 0.09 69280/69283 compare/3(0) [9] -----------------------------------------------
The first entry is `call_engine_label' and its parent is `<spontaneous>', meaning that it is the root of the call graph. (The first three entries, `call_engine_label', `do_interpreter', and `io__run/0' are all part of the Mercury runtime; `main/2' is the entry point to the user's program.)
Each entry of the call graph profile consists of three sections, the parent procedures, the current procedure and the children procedures.
Reading across from the left, for the current procedure the fields are:
The predicate or function names are not just followed by their arity but also by their mode in brackets. A mode of zero corresponds to the first mode declaration of that predicate in the source code. For example, `list__delete/3(3)' corresponds to the `(out, out, in)' mode of `list__delete/3'.
Now for the parent and child procedures the self and descendent time have slightly different meanings. For the parent procedures the self and descendent time represent the proportion of the current procedure's self and descendent time due to that parent. These times are obtained using the assumption that each call contributes equally to the total time of the current procedure.
This section contains a brief description of all the options available for `mc', the Mercury compiler. Sometimes this list is a little out-of-date; use `mc --help' to get the most up-to-date list.
mc
is invoked as
mc [options] modules
For module names, the trailing `.m' is optional.
Options are either short (single-letter) options preceded by a single `-', or long options preceded by `--'. Options are case-sensitive. We call options that do not take arguments flags. Single-letter flags may be grouped with a single `-', e.g. `-vVc'. Single-letter flags may be negated by appending another trailing `-', e.g. `-v-'. Long flags may be negated by preceding them with `no-', e.g. `--no-verbose'.
-w
--inhibit-warnings
--halt-at-warn.
--halt-at-syntax-error.
--no-warn-singleton-variables
--no-warn-missing-det-decls
--no-warn-det-decls-too-lax
--no-warn-nothing-exported
--warn-unused-args
--warn-interface-imports
--warn-missing-opt-files
--warn-non-stratification
-v
--verbose
-V
--very_verbose
-E
--verbose-error-messages
-S
--statistics
-T
--debug-types
-N
--debug-modes
--debug-det, --debug-determinism
--debug-opt
--debug-vn <n>
-M
--generate-dependencies
-i
--make-interface
--make-short-interface
--make-optimization-interface
-G
--convert-to-goedel
-P
--pretty-print
--convert-to-mercury
--typecheck-only
-e
--errorcheck-only
-C
--compile-to-c
--compile-to-C
-c
--compile-only
--no-assume-gmake
--generate-bytecode
--generate-prolog
--prolog-dialect dialect
--auto-comments
-n
--line-numbers
--show-dependency-graph
-d stage
--dump-hlds stage
-D
--verbose-dump-hlds
See the Mercury language reference manual for detailed explanations of these options.
--no-reorder-conj
--no-reorder-disj
--fully-strict
error/1
.
--infer-types
--infer-modes
--no-infer-det, --no-infer-determinism
The following compilation options affect the generated code in such a way that the entire program must be compiled with the same setting of these options, and it must be linked to a version of the Mercury library which has been compiled with the same setting. Rather than setting them individually, you must specify them all at once by selecting a particular compilation model ("grade").
-s grade
--grade grade
--debug --no-c-optimize
.
--gcc-global-registers
.
--gcc-nonlocal-gotos
.
--gcc-global-registers --gcc-nonlocal-gotos
.
--gcc-nonlocal-gotos --asm-labels
.
--gcc-global-registers --gcc-nonlocal_gotos --asm-labels
.
--gc conservative
.
--profiling
.
Reminder: the following optimizations should not be set individually. Instead, you should use the `--grade' option to change the setting of these options.
--gcc-global-registers
(grades: reg, fast, asm_fast)
--no-gcc-global-registers
(grades: debug, none, jump, asm_jump)
--gcc-non-local-gotos
(grades: jump, fast, asm_jump, asm_fast)
--no-gcc-non-local-gotos
(grades: debug, none, reg)
--asm-labels
(grades: asm_jump, asm_fast)
--no-asm-labels
(grades: debug, none, reg, jump, fast)
--gc {none, conservative, accurate}
--garbage-collection {none, conservative, accurate}
--tags {none, low, high}
--num-tag-bits n
--have-delay-slot
--num-real-r-regs n
--num-real-f-regs n
--num-real-r-temps n
--num-real-f-temps n
--profiling
(grades: any grade ending in `.prof')
--debug
(grades: debug)
--args {old, compact}
--arg-convention {old, compact}
--no-type-layout
--no-trad-passes
--no-reclaim-heap-on-nondet-failure
--no-reclaim-heap-on-semidet-failure
--cc compiler-name
--c-include-directory dir
--cflags options
-O n
--opt-level n
--optimization-level n
--opt-space
--optimize-space
--intermodule-optimization
--split-c-files
These optimizations are high-level transformations on our HLDS (high-level data structure).
--no-inlining
--no-inline-simple
--no-inline-single-use
--inline-compound-threshold threshold
--inline-simple-threshold threshold
--intermod-inline-simple-threshold threshold
--no-common-struct
--no-common-goal
--no-follow-code
--no-optimize-unused-args
--no-optimize-higher-order
--optimize-constructor-last-call
--optimize-dead-procs.
--excess-assign
--optimize-saved-vars
These optimizations are applied during the process of generating low-level intermediate code from our high-level data structure.
--no-static-ground-terms
--no-smart-indexing
--dense-switch-req-density percentage
--dense-switch-size size
--lookup-switch-req-density percentage
--lookup-switch-size size
--string-switch-size size
--tag-switch-size size
--no-middle-rec
--no-simple-neg
--no-follow-vars
These optimizations are transformations that are applied to our low-level intermediate code before emitting C code.
--no-llds-optimize
--no-optimize-peep
--no-optimize-jumps
--no-optimize-fulljumps
--no-optimize-labels
--optimize-dups
--optimize-value-number
--no-optimize-frames
--no-optimize-delay-slot
--optimize-repeat n
--optimize-vnrepeat n
These optimizations are applied during the process of generating C intermediate code from our low-level data structure.
--no-emit-c-loops
--use-macro-for-redo-fail
--procs-per-c-function n
--no-c-optimize
-I dir
--search-directory dir
-?
-h
--help
-o filename
--output-file filename
--link-flags options
-L directory
--library-directory directory
-l library
--library library
--link-object object
The shell scripts in the Mercury compilation environment will use the following environment variables if they are set. There should be little need to use these, because the default values will generally work fine.
MERCURY_DEFAULT_GRADE
MERCURY_OPTIONS
MERCURY_C_INCL_DIR
MERCURY_INT_DIR
MERCURY_NC_BUILTIN
MERCURY_C_LIB_DIR
$MERCURY_C_LIB_DIR
.
MERCURY_NONSHARED_LIB_DIR
MERCURY_MOD_LIB_DIR
MERCURY_MOD_LIB_MODS
MERCURY_NU_LIB_DIR
MERCURY_NU_LIB_OBJS
MERCURY_COMPILER
MERCURY_INTERPRETER
MERCURY_MKINIT
The Mercury compiler takes special advantage of certain extensions provided by GNU C to generate much more efficient code. We therefore recommend that you use GNU C for compiling Mercury programs. However, if for some reason you wish to use another compiler, it is possible to do so. Here's what you need to do.