mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-09 10:52:24 +00:00
Estimated hours taken: 120
Connect the Mercury compiler to the GCC back-end.
These changes give us a version of the Mercury compiler which
compiles to assembler without going via any intermediate files.
This version generates GCC's `tree' data type, and then calls functions
in the GCC middle-end to convert that to GCC's RTL (Register Transfer
Language) and to invoke the rest of the GCC middle-end and back-end
to compile it to assembler.
RATIONALE
The main advantage is improved compilation speed.
(The improvement is not huge, since the current front-end is so slow,
but improving the speed of the back-end increases the incentive to
improve the speed of the front-end, since it means that any increases
in the speed of the front-end will get bigger overall speedups.)
Another advantage is that it gives us more opportunity to give the GCC
back-end information about how to optimize the code that we generate.
For example:
- We can tell GCC when it is safe to treat function calls
as tail calls. (The gcc back-end already has some support
for doing tail calls. But its check to determine when
it is safe to do them is much too conservative for Mercury.
I've been working on extending the gcc back-end infrastructure
so that front ends can tell the gcc back-end when it is safe.)
- We can use `__builtin_{set,long}jmp' rather than ordinary
`{set,long}jmp'. (We can also do this for the C back-end,
as it happens, since those are supported in GNU C too, but
I wouldn't have found out about it if not for doing this
back-end.) Or we can use gcc's exception handling;
the gcc developers have told me that using exception
handling may be more efficient on some platforms.
- We can mark GC_malloc as an allocation function,
so that GCC knows that stuff allocated with it won't
alias other pointers.
- In general we could give GCC more information about aliasing.
I haven't investigated this much yet, but I think the GCC
back-end has support for keeping track of alias sets and
recording which set each pointer points to and which sets
may be subsets of which other sets.
Another advantage is that it provides a demonstration of how to
compile logic languages or functional languages using the GNU C
back-end. This may be useful to researchers or open-source developers
who are working on other languages.
It is also good public relations, because it removes one more
barrier towards acceptance of Mercury. Some people want a language
implementation that has a "native code compiler", and don't want one
that compiles via C. These people may be more willing to consider
Mercury now.
gcc/mercury:
New directory.
This contains the C side of the Mercury <-> GCC interface.
gcc/mercury/Make-lang.in:
gcc/mercury/config-lang.in:
gcc/mercury/lang-specs.h:
Makefile/configure/specs fragments (respectively)
that are required by GCC.
gcc/mercury/lang-options.h:
Documents the Mercury-specific gcc options,
in particular the `--mmc-flag=' option.
gcc/mercury/mercury-gcc.c:
gcc/mercury/mercury-gcc.h:
This is the "meat" on the C side of the Mercury <-> GCC interface.
These files provide the C code that GCC requires of each
language front-end. They also define some routines for
building parts of the GCC `tree' data structure that are
used by the Mercury compiler.
gcc/mercury/Makefile:
A Makefile which just runs `make mercury' in the parent directory.
Just for convenience.
gcc/mercury/README:
gcc/mercury/ChangeLog:
Some (very basic) documentation.
gcc/mercury/test.m:
A sample Mercury module, to serve as a simple test case.
gcc/mercury/testmercury.c:
C driver program for the test Mercury module.
mercury/compiler/gcc.m:
New file. This is an interface to the tree data structure defined
in gcc/tree.h, and to functions for manipulating that data structure
which are defined in gcc/mercury/mercury-gcc.c and in other parts
of the GCC back-end. It's almost entirely composed of simple
pragma c_code routines that each just call a single C function.
mercury/compiler/mlds_to_gcc.m:
New file. This converts the MLDS into the gcc tree representation
whose interface is in gcc.m, using the routines defined in gcc.m.
This is the "meat" on the Mercury side of the Mercury <=> GCC interface.
mercury/compiler/globals.m:
Define new target `asm', for compiling directly to assembler
(without any intermediate files), via the gcc back-end.
mercury/compiler/handle_options.m:
`--target asm' implies `--high-level-code'.
mercury/compiler/mercury_compile.m:
Handle `--target asm' by invoking mlds_to_gcc.m.
mercury/main.c:
New file, containing main() that calls mercury_main().
mercury/compiler/Mmakefile:
Add C2INITFLAGS=--library, so that we can link `libmercury_compile.a'
as a library without main(). For the mercury_compile executable,
get main by linking in ../main.o.
Add `libmmc' target, for building libmercury_compile.a and
mercury_compile_init.a.
Add the appropriate `-D' and `-I' options to CFLAGS-gcc so that we
can compile gcc.m.
mercury/runtime/mercury.c:
Define out-of-line copies of MR_box_float() and MR_unbox_float(),
so that the new `--target asm' back-end can generate calls to them.
mercury/runtime/mercury.h:
mercury/runtime/mercury_heap.h:
Add comments warning about code duplication between
the inline and out-of-line versions of various functions.
mercury/Makefile:
mercury/Mmakefile:
Add `libmmc' target, for use by gcc/mercury/Make-lang.in.
mercury/runtime/mercury_std.h:
When IN_GCC is defined, use safe_ctype.h rather than
ctype.h, since the latter conflicts with the GCC headers.
Comment out the definition of the `reg' macro, since
that too conflicts with the GCC headers.
mercury/runtime/mercury_dlist.c:
mercury/runtime/mercury_hash_table.c:
mercury/runtime/mercury_stacks.h:
Delete unnecessary uses of the `reg' macro.
36 lines
1.2 KiB
C
36 lines
1.2 KiB
C
/*
|
|
** Copyright (C) 2000 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU General
|
|
** Public License - see the file COPYING in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** main.c
|
|
**
|
|
** This file defines the main() function for the `compiler/mercury_compile'
|
|
** executable. We define main() separately here,
|
|
** because compiler/mercury_compile is built as a library;
|
|
** this is necessary for the GCC back-end port, where the
|
|
** mercury_compile library is linked together with the
|
|
** GCC back-end into the `cc1mercury' program,
|
|
** whose main() function is defined in gcc/toplev.c.
|
|
**
|
|
** The main() function here just calls mercury_main().
|
|
** mercury_main() is defined in compiler/mercury_compile_init.c,
|
|
** which is automatically generated (by scripts/c2init,
|
|
** which invokes mkinit, whose source is in util/mkinit.c).
|
|
** It initializes the Mercury runtime and then calls the
|
|
** main/2 predicate, which is defined compiler/mercury_compile.m.
|
|
**
|
|
** For general information about the design of the Mercury compiler,
|
|
** see compiler/notes/compiler_design.html.
|
|
*/
|
|
|
|
extern int mercury_main(int argc, char *argv[]);
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
return mercury_main(argc, argv);
|
|
}
|