home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d466
/
dice
/
compiler.doc
< prev
next >
Wrap
Text File
|
1991-03-08
|
14KB
|
364 lines
compiler/compiler compiler/compiler
compiler/COMPILER compiler/COMPILER
DICE SYSTEM
Matthew Dillon
891 Regal Rd.
Berkeley, Ca. 94708
USA
dillon@overload.Berkeley.CA.US
uunet.uu.net!overload!dillon
BIX: mdillon
COMPILER FEATURES LIST AND ORGANIZATION
NOTE: net distributed releases will not contain
commodore includes or amiga*.lib
(1) Organization of includes and libraries, default:
DINCLUDE: location of top level includes such as stdio.h
DINCLUDE:Amiga/ location of amiga includes (e.g. amiga/exec/types.h)
(amiga includes not included)
NOTE !!! Amiga includes should be placed in the subdirectory
dinclude:Amiga, that is, dinclude:Amiga/Exec/*.h,
dinclude:Amiga/graphics/*.h, etc...
DCC references startup and libraries to DLIB:
DLIB:amigas.lib A small-data model version of AMIGA.LIB
DLIB:c.lib The main C library for which you have source code
DLIB:m.lib The math library
DLIB:auto.lib The auto library-open library
DLIB:c.o The startup module
DLIB:x.o The terminator module
(2) Organization of includes and libraries, -2.0 option (usually
set in the DCCOPTS enviroment variable)
DINCLUDE:AMIGA20/ instead of DINCLUDE:AMIGA
DLIB:amigas20.lib instead of DLIB:amigas.lib
(3) DCC generated link lines
If you give DICE the following line:
1> DCC foo.o -o foo
It will run DLink with the following options:
DLink dlib:c.o foo.o dlib:c.lib dlib:amigas.lib dlib:auto.lib dlib:x.o -o foo
DLIB:C.O DICE startup code
FOO.O your object module(s)
DLIB:C.LIB DICE C.LIB
DLIB:AMIGAS.LIB small data model version of commodore amiga.lib
DLIB:AUTO.LIB DICE AUTO.LIB
DLIB:X.O DICE section terminator code
Some explanation is in order. AUTO.LIB catches any references
to common library base variables when no storage has been
declared and imports code to automatically open said libraries
on startup and close them on exit. DICE uses this feature to
import code to open and close "dos.library" when DOSBase is
referenced, and also for the floating point libraries.
X.O is used to supply an RTS at the end of the special autoinit
and autoexit sections. Any module between C.O and X.O may
declare these special sections to handle run-time relocations and
other DICE features, and do so such that when the base of the
section is JSR'd all the various module's code is sequenced
through until the RTS in X.O is hit for the sections in
question.
(4) SMALL DATA AMIGA.LIB
DICE uses a small-data model version of Commodore's AMIGA.LIB
to allow it to generate residentable executables (-r option to
DCC). The small data amiga.lib, called AMIGAS.LIB (note the 's')
is generated from the large modem amiga.lib with the LIBTOS
program.
LIBTOS, including source, is included. The source is available
to allow developers using DICE to add new base variables to
LIBTOS's search list when new operating systems come out without
having to wait for my update.
----------------------------------------------------------------------
COMPILER FEATURES LIST
(0) ANSI. Pretty much ansi. Please report non-ansism problems. Check
out the doc/KnownBugs list before reporting a problem.
(1) autos are placed in registers based on weighted usage. A0,A1,D0,D1
will be used as register variables whenever possible, which usually
reduces the number of registers that must be saved/restored in
critical low level routines. The 'register' keyword is
essentially ignored (use 'volatile' to force a variable to NOT
be in a register).
(2) LINK/UNLK is removed from low level routines that do not reference
A5 and do not make any subroutine calls.
(3) MOVEM is converted to MOVE or deleted entirely when possible.
(4) Various obvious optimizations: use of BSET, BCLR, BTST as short
cuts to logic operations, CMP/TST, etc...
(5) Switch() statements are optimized as follows:
* if the range of values is less than double the number of cases
a lookup table will be used
* if a small number of cases exists a sub[q]/beq sequence
will be used
* for a sufficiently large set of cases that cannot be made
into a jump table, a binary subdivision method is used.
(6) Branch optimization. Bxx to BRAs are optimized (up to 20 hops) by
DAS, and massive optimization is done to multi-level conditionals
by the main compiler pass.
(7) Workbench support. The standard startup module supports the workbench.
Specifically, the low level _main() in c.o does this.
When a program is run from the workbench, a different entry point is
called: wbmain(wbmsg)
If you do not supply a wbmain() then the one from the c.lib library
is used which immediately return(-1)s, exiting the program.
The standard return from wbmain() or using exit() automatically
ReplyMsg()s the workbench message for you.
(8) _main() shortcut for extremely low level programs.
You may overide c.lib's _main with your own. If you do so you may
not use any c.lib memory allocation, stdio, or fd (open,close...)
related routines. The startup module (c.o) will still run
autoinits, autoexits, setup resident programs, and initialize your
BSS space.
_main(len, arg) (as passed to the program on startup)
long len;
char *arg;
{
}
If running from the workbench, you must GetMsg() and process the
workbench startup message yourself, as well return the message
when you exit.
_exit exists in c.o and cannot be overridden. If you use the _main
override you may NOT call exit() unless you also override it.
Calling exit() will generate references to stdio library code and
bring it in from the library, making your executable larger
unnecessarily.
i.e. if you use _main() you should either fall through or use
_exit() to exit.
(9) AutoInit support. You may qualify a subroutine with the __autoinit
keyword that will cause it to be automatically called by the
startup code rather than having to explicitly call it from main.
This feature is more useful to bring code in indirectly. For
example, to automatically OpenLibrary() (& CloseLibrary()) floating
point libraries if their base variables are referenced.
Refer to the auto.lib source code for examples.
__autoexit works the same way. Note that __autoinit routines are
called BEFORE _main, just after autoinit libraries are openned,
and __autoexit routines are called in __exit just before autoinit
libraries are closed.
(10) DCC runs fast. Make everything resident and watch it fly. Most
of this speed comes from loading entire files into memory at once.
This might present a memory problem, but in general DICE's memory
usage is comparable to Lattice and Aztec.
(11) CODE SIZE is comparable with Lattice and Aztec, even better in
many cases. The minimum program sizes are as follows:
_main() { } 448 no stdio/fd
main() { } 2736 some stdio
main() { printf..} 5492 most of stdio
(12) EXTENSIONS , see EXTENSIONS.DOC. DICE provides many extensions
to C to support various AMIGAisms and ROM based code, including
special treatment of the 'const' storage qualifier.
(13) The preprocessor is able to handle arbitrarily sized macros. There
are no limits to symbol or macro length. The preprocessor is able to
handle up to 64 levels of includes / macro recursions with arbitrary
use of the string-ize (#) and token pasting (##) operators.
The preprocessor implements the __BASE_FILE__ macro as well as all
standard ANSI macros (__FILE__, __LINE__, __DATE__, __TIME__, ...)
(14) DICE supports the creation of residentable executables in nearly
all cases (exception: using the __geta4 procedure qualifier
precludes being able to make an executable resident, also non
const __chip data).
Not only is residentability supported, but it is supported
without requiring the programmer to #include all sorts of
prototype/pragma files.
(15) DICE supports the small-data model, large data model, small and
large code models, and special data models (word absolute,
absolute known address) for supporting ROMable code. The linker
automatically generates JMP tables when the small-code model is
used in large executables.
(16) REGISTERED user's DICE supports __chip, __near, and __far keywords,
as well as others.
(17) Simplified library and startup module design. There are no multiple
versions of a single library for different memory models and the
frontend, DCC, makes all library and startup module interaction
except m.lib invisible. The same c.o handles both resident and
non-resident startup. c.lib and m.lib may be used with programs
that declare more than 64KBytes of BSS (though not with programs
that declare more than 64KBytes of __near initialized storage).
There is no large-data-model version of c.lib and m.lib,
although you can easily recompile the libraries into a large-data
model version if you wish. I suggest that instead of doing that
you stick with the small-data model and use the __geta4 type
qualifier to procedures which are called out of context.
(18) Optimization of args to prototyped routines
--------------------------------------------------------------------------
GOALS
In writing DICE my goals are as follows:
- reasonably fast compilation. Modular executables for ease of use,
reliability, and testability.
- concentrate more on reliability and less on optimizations. Remember that
this is only the third major distribution of DICE, I expect some bugs
to show up. I expect to become more reliable than the two other
commercial C compilers in the Amiga market within a year.
- but do not forget optimizations... put in relatively easy to implement
optimizations that do not destroy the reliability of DICE. DICE does
no common sub-expression or loop unrolling optimizations, but does do
relatively smart register allocation and multi-level history to
propogate conditional expressions.
- provide comprehensive support of the Amiga, especially for new
versions of the OS that come out.
- I have always torn my hair out at not being able to easily fix bugs in
the support libraries for commercial compilers. DICE includes full
source for its support libraries (c.lib, m.lib, auto.lib) and a means
to remake the library. DICE also includes full source to some of
its own utilities, namely LIBTOS and the DCC frontend which are the
most likely candidates for programmer hair loss.
------------------------------------------------------------------------
COMMENTS
Registerized parameters are not implemented. While such a feature
would make an executable somewhat smaller and a little faster, a few
percent of gain is not worth the complexity of the implementation (and
thus the possibility of introduced bugs). The difference in execution
speed is generally so miniscule that it isn't noticable, and where it
is noticable it is usually due to a badly implemented algorithm in
the first place.
So, cute, but not as much of a boost as you might think.
Inline library calls are not implemented either. Inline library calls
are actually useful and when properly implemented increase efficiency
to low level calls such as AddHead() and GetMsg(). Other calls such as
Move() and Draw() do not increase noticably in efficiency. #pragma's
must be used to define inline calls and this makes the compiler
enviroment less portable. Lattice made a big mistake *requiring* the
use of inline library calls with residentable programs. My solution
was to write a program to convert AMIGA.LIB into a small-data version
of same called AMIGAS.LIB.
In general, I refuse to implement a thousand nearly useless features
that will only introduce more bugs into the compiler.
------------------------------------------------------------------------
COMPATIBILITY
ANSI C
DICE is getting closer to being ANSI C compliant, there are only a
few things missing.
I spent a great deal of time ensuring that STDIO routines run relatively
fast. I decided to write nearly all of the support library in C instead
of falling back to optimized assembly to keep the system uniform and
portable. One does not notice much of a difference between the C
strcpy() and an assembly strcpy() relative to the run time of their
program.
AMIGA
As said in feature (7), if you wish your program to be runnable from
the workbench you must supply a wbmain() entry point. If you do not
then running the program from the workbench will result in its
immediate termination (e.g. nothing happens). On return from wbmain()
or exit() the workbench message is automatically ReplyMsg()d by the
exit code.
DICE separates workbench startup and puts it in the hands of the user
to simplify the user's code. Since there are two entry points,
main() for CLI run programs and wbmain() for WORKBENCH-run programs,
the programmer can more easily modularize his code.
The Registered release of DICE supports the __near, __far, and __chip
keywords.
UNBUFFERED CONSOLE IO
You may set a console to RAW mode using the setbuf() and setvbuf() calls.
You may set a console back to COOKED mode using the same calls.
------------------------------------------------------------------------
Your first program
1> cd examples
1> dcc hello.c -o ram:hello
1> ram:hello
hello world
1>
Your first residentable program
1> cd examples
1> dcc hello.c -o ram:hello -r
1> ram:hello
hello world
1> resident ram:hello
1> hello ; instantanious execution
hello world
1>
* NOTE, a common problem is that users have removed various floating
point libraries from LIBS: and this will prevent DC1 from running.
Make sure you have the full complement of floating point libraries
in LIBS: