[fa.info-mac] Consulair Corp Mac C Compiler and Toolkit

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
 
-------
-------