info-mac@uw-beaver.UUCP (11/02/84)
From: Mike Schuster <MIKES@CIT-20.ARPA>
Consulair Corp's Mac C Compiler and Toolkit
I received Consulair Corp's Compiler and Toolkit last week. Here are
some my feelings about its good and bad points, along with a list of
undocumented bugs and workarounds.
* Overview
Consulair Corp (415) 851-3849 Mac C compiler translates C programs into
68000 assembly language for Apple's Macintosh 68000 Development System.
It runs on both 128k and 512k Macs with hard disk or external drive, or
a Lisa running MacWorks. It requires the Editor, Assembler, Linker,
and Exec portions of the Development System.
The Mac C Toolkit is a collection of C and assembler routines that
implement a variety of useful I/O, math, string, memory, and utility
functions.
The Compiler and Toolkit list for $425, add $25 for a copyable version.
* Mac C Compiler Hilites
-- Supports code segmentation via standard Toolbox segment loader.
-- Supports standard Apple family of debuggers.
-- Calls to stack based Toolbox routines and register based Operating
System routines are emitted inline with no "glue routines".
-- Source ".h" header files give system values and C structure
definitions. (Header files based in part on Stanford's SUMEX
project SUMACC Development System).
-- Mac C was used to write the Assembler, Linker, Editor, and Exec
portions of the Macintosh 68000 Development System.
-- Supports a Lisp-like Signal/CatchSignal function escape mechanism.
* Mac C Toolkit Hilites
-- I/O package for synchronous or multiply buffered asynchronous I/O.
-- Complete Standard C I/O and Memory Routines (printf, malloc, ...).
-- TTY window emulation package.
-- Source code included. Extract, modify and compile/assemble only
those routines that seem most useful.
* Mac C versus "Standard C"
-- Floating point types Float, Double, Comp, and Extended are not
implemented.
-- Bit fields in structure are not implemented.
-- Enumerated types are not implemented.
-- Register variables are implemented as normal stack variables.
-- Structures passed by value and functions returning structures
are not implemented.
-- All characters in an identifier are significant.
-- All field names are local in scope to the structure in which they
are declared.
-- Type and field checking is carried out through all levels of
indirection.
-- Inline assembly code allowed between #asm and #endasm.
-- Integer size may be either 16 or 32 bits. (Compile time option).
-- Literal values can be cast to structures and structure pointers.
-- Literals and identifiers may be cast on the left side of assignments.
-- Scope of structure is always from definition point to end of file,
even if structure is declared within a function.
-- Local variables may not be redefined within a subordinate block.
* Code Generation
-- First seven arguments to C functions are passed in registers D0-D6.
-- Rest of arguments (if any) are pushed on the stack.
-- Arguments to Toolbox routines are passed on the stack or in registers
as appropriate. Trap instruction emitted inline.
-- Register D0 contains the result of the function call if the result is
a value; A0 contains the result if it is a pointer.
-- Functions must preserve ONLY registers A5, A6, and A7.
-- Switch statements are implemented as a sequence of tests followed by
conditional jumps.
-- Common subexpressions are not identified, nor is register usage
or condition code state tracked to eliminate redundant loads, stores,
and tests.
* Run Time
-- External variables are stored relative to A5 or optionally in a
Global Data Segment allocated at start up. Global Data Segment
may be refered to via A0, ..., A4 (Compile time option). (Useful for
desk accessories.)
-- Constants (other than those used to initialize external variables)
are stored as operands to instructions or as data after the final
instruction in the segment. String constants are of the latter form.
-- Startup code (580 bytes) consists of a few long integer math and
string routines, the Signal/CatchSignal routines, and a routine
that copies initialized external variable values from a resource in
the compiled application program to either A5 relative or into
the Global Data Segment. Source for Startup is included and may
be easily modified.
-- Taking the address of a function in a segment other than segment 1
produces the address of the jump table entry so that calls will
invoke the segment loader properly.
* Watch Out
-- Since string constants are stored in code segments, avoid taking
the address of a string constant and then unloading the
segment containing the string.
-- All identifiers are converted to uppercase ASM, so case sensitivity
is NOT carried outside the source file. For example:
extern char *PtoCStr();
char *p;
p = PtoCstr("foo"); /* notice the lower case 's' */
Since PtoCstr (lower case s) is undeclared, Mac C assumes it returns
an integer, and so emits code to move the expected result in D0 to p.
Assembler and Linker, however, bind PtoCstr to the existing Toolkit
routine PtoCStr (upper case s), which returns its result in A0.
So, DON'T forget to declare external functions returning pointers.
* A Few Undocumented Bugs and Workarounds (Mac C 1.05, 10/29/84)
-- Indexed array address computation sign extends unsigned short
indicies and hence fails for values greater than 32K. To fix,
declare index variables long.
-- Comma expressions can only be used in expressions immediately
following FOR and WHILE.
-- Brackets must not be placed around single initializers, use
int x = 1;
rather than
int x = {1};
-- Bad code is sometimes generated when constants are used in
conditional expressions, use
#define debug
#ifdef debug
if (x)
...
#endif
rather than
#define debug 1
if (x && debug)
...
-- Global variable QD is improperly initialized at startup. Add
4 to QD to get the proper value.
-- Startup code fails if A4 is used as the Global Data Segment
index register.
-- The first field of an external structure may not be properly word
aligned.
Mike Schuster
@cit-20
-------
-------