3. How to use C Compiler

3.1. How to Compile this Compiler

The COINS infrastructure includes the class coins.driver.Driver that serves as the driver of a C compiler. The target machine architecture can be selected from the following list:

Note: (Status at November 2006)
All of above target options have been tested by using test programs under the directory test/c and succeeded to execute correctly except for a few number of special cases. As for the sparc and x86, the compiler passed the test by comprehensive test program set composed of 8000 programs and successfully executed the SPEC CPU 2000 benchmark programs. (When -O3 option is specified, some programs in SPEC CPU 2000 fails yet.) When target=arm is specified, a few programs in SPEC CPU 2000 can be executed successfully but others failed because of restrictions from test environment and remaining defects in code generation. As for other targets (mb, mips, ppc, sh4, thumb, alpha), test by SPEC CPU2000 is not yet tried.

The compilers for sparc and x86 support the "long long" type, while the others do not support it.

All the classes of COINS are precompiled into the directory 'classes', so you can try to compile your C programs immediately.

If you wish to compile the compiler yourself, do the following:

3.2. How to Execute the Compiler

3.2.1. Short Descriptions

Follow the following procedures:

On UNIX running a sh-compatible shell, type

     export CLASSPATH=$HOME/Java/coins-1.x.y/classes
            ## Change according to your environment.
or for Windows
     SET CLASSPATH=c:\home\Java\coins-1.x.y\classes
            ## Change according to your environment.
Then on either platform type
     java coins.driver.Driver -S xxx.c
or
     java -classpath ./classes coins.driver.Driver -S xxx.c
To specify the target machine add the option "-b arch" to the above command, where arch is sparc, sparc-v8, x86, arm, mips, sh4, or ppc. The default is "sparc".

Debug information will be printed if the following command is used.

     java coins.driver.Driver -S -coins:trace=Sym.1/HIR.1/back xxx.c
or
     java -classpath ./classes coins.driver.Driver -S  -coins:trace=Sym.1/HIR.1/back xxx.c
(if class files are under 'classes') where, "trace= ..." specifies debug control and the number "1" in "Sym.1", etc. is a trace level. "Sym" in "Sym.1" is a trace category. Large trace categories number (e.g. 500, 10000) may produce a huge amount of debug print.
Available trace categories are described in "2.3.4. -coins Options" of 2. How to use the Compiler Driver.

Object code (xxx.s) will be generated on the same directory as that of source program xxx.c. It can be executed by

     cc xxx.s; ./a.out or ./a.exe
For more information on C compiler driver coins.driver.Driver, see 2. How to use the Compiler Driver.

3.2.2. Required Software

COINS C compiler driver requires following commands to execute compilation: Prior to compilation, make sure that you can invoke these commands (i.e., include them in your execution path). If you don't have these commands but have alternatives (e.g., 'as' for 'gas'), the driver provides a way to specify alternative commands.

For more detail, see

options described in "2.3.4. -coins Options" of 2. How to use the Compiler Driver.

3.3. Source language

3.3.1. C language

This compiler supports language facilities specified in except for following features: As for preprocessor and library, it is recommended to use those of gcc.

3.3.2. "asm" statement

The syntax of the asm-statement is the following:
  asm("#param descriptor-list\n"
      "#clobber destroyed registers...\n"
      "instruction 1\n"
             ...
      "instruction n\n",
      input arguments(any expression)...);

 descriptor-list:
    descriptor
    descriptor-list , descriptor
 
 descriptor:
    %register
    %register-class-name         /* input parameter, actual parameter is rvalue */
    w%register
    w%register-class-name        /* output parameter, actual parameter is lvalue */
    m%register
    m%register-class-name        /* input and output parameter, actual parameter is lvalue */
    s          /* actual parameter is static address */
 
 register:
    register-name
 
 register-class-name:
    register-class-name defined in the TMD file.

Example 1:

asm-statement for "z = x + y;"
 asm("#param %I32,%I32,w%I32\n"
     " mov %1,%3\n"
     " add %2,%3\n",
     x, y, z);

example 2:

asm-statement for "x++;"
 asm("#param m%I32\n"
     "  add 1,%1\n",
     x);
3.3.2.1. HIR of "asm" statement
The HIR form of an asm-statement is the following:
 * AsmStmt    ->        //
 *    ( asmCode attr    // Asm statement.
 *      StringConstNode_ @ //String constant representing formal parameters
 *                       // and sequence of assembly language instructions.
 *      HirList @ )        // List of l-value expressions (variable nodes,
 *                      // pointer expressions, etc.) and arithmetic
 *                      // expressions representing actual parameters.

Example 1:

source program:
int x, y, z;
int main()
{
  int a, b, c;
  a = 1;
  b = a + 2;
  z = -1;
  asm("#param %I32, %I32, w%I32\n"
      "mov %1,%3\n"
      "add %2,%3\n",
      a, b+1, z);
  printf("a=%d b=%d z=%d \n", a, b, z);
  return 0;
}
HIR for the above program is the following:
 (prog     1
  <null 0 void>
  <nullNode 2>
  (subpDef  3 void
   <subp     4 <SUBP <( )> false false int> main>
  <null 0 void>
   (labeldSt 5 void
    (list 6
     <labelDef 7 _lab1>)
    (block    8 void line 2
     (assign   9 int line 5
      <var      10 int a>
      <const    11 int 1>)
     (assign   12 int line 6
      <var      13 int b>
      (add      14 int
       <var      15 int a>
       <const    16 int 2>))
     (assign   17 int line 7
      <var      18 int z>
      (neg      19 int
       <const    20 int 1>))
     (asm      21 void line 8
      <const    22 <VECT 46 0 char> "#param %I32, %I32, w%I32\nmov %1,%3\nadd %2,%3\n">
      (list 23
       <var      24 int a>
       (add      25 int
        <var      26 int b>
        <const    27 int 1>)
       <var      28 int z>))
     (expStmt  29 int line 12
      (call     30 int
       (addr     31 <PTR <SUBP <( )> false true int>>
        <subp     32 <SUBP <( )> false true int> printf>)
       (list 33
        (decay    34 <PTR char>
         <const    35 <VECT 17 0 char> "a=%d b=%d z=%d n">)
        <var      36 int a>
        <var      37 int b>
        <var      38 int z>)))
     (return   39 int line 13
      <const    40 int 0>)))))

Example 2:

asm-statement:
  asm("#param %I32, m%I32\n"
      "add %1,%2\n",
      i, j);  /* j = j + i; */
HIR for the above statement is the following:
     (asm      17 void line 11
      <const    18 <VECT 30 0 char> "#param %I32, m%I32\nadd %1,%2\n">
      (list 19
       <var      20 int i>
       <var      21 int j>))
3.3.2.2. LIR of "asm" statement
The syntax of LIR generated from an asm-statement is the following:
(ASM <body-string> <in-list> <out-list> <inout-list>
     &argtype <arg-list>
     &clobber <clobber-list>)

Example 1:

asm-statement:
asm("#param w%I32,%I32,%I32\n"
    "#clobber %eax,%ebx\n"     /* unrealistic example */
    " mov %2,%1\n"
    " add %3,%1\n",
    z, x+1, y);
LIR generated from the above statement is the following:
(ASM " mov %1,%3\n add %2,%3\n"  ; numbers are changed
     ((ADD I32 (MEM I32 (FRAME I32 "x") (INTCONST I32 1)) (MEM I32 (FRAME I32 "y")))   ;in-list
     ((MEM I32 (FRAME I32 "z")))   ;out-list
     ()	      ;inout-list
     &argtype (%I32 %I32 w%I32)
     &clobber (%eax %ebx))  
This is further transformed and becomes finally to:
(SET I32 (REG I32 ".t1%") (ADD I32 (REG I32 "x%") (INTCONST I32 1)))
(PARALLEL
   (ASM " mov %1,%3\n add %2,%3\n"	;body
        ((REG I32 ".t1%") (REG I32 "y%"))	;in-list
        ((REG I32 "z%"))			;out-list
        () )				;inout-list
        (CLOBBER (REG I32 "%eax") (REG I32 "%ebx")))

Example 2:

source program:
 int vec[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 
 int foo(int i) {
   int autov = i;
   int x;

   /* x = vec[i] + autov; */
   asm("#param %I32,s,%I32,w%I32\n"
       " movl %2(,%3,4),%4\n"
       " addl (%1),%4\n",
       &autov, vec, i, x);
   return x;
 }
LIR generated from the above asm-statement is the following:
 (ASM " mov %2(,%3,4),%4\n add %1(%%ebp),%4\n"
      ((FRAME I32 "autov") (STATIC I32 "vec") (REG I32 "i%"))
      ((REG I32 "x%"))
      ()
      &argtype (a s %I32 w%I32))

  (ASM " movl %2(,%3,4),%4\n addl (%1),%4\n"
      ((FRAME I32 "autov.5") (STATIC I32 "vec") (MEM I32 (FRAME I32 "i.4")))
      ((MEM I32 (FRAME I32 "x.6"))) ()
       &argtype (%I32 s %I32 %I32))
The final assembly form is:
  ;i:%ebx, x:%eax, &autov:%edx
  leal -4(%ebp),%edx
  movl vec(,%ecx,4),%eax
  addl (%edx),%eax

3.4. Automatic Test of the Compiler

Many test programs are prepared under test/c directory.
They are arranged for automatic test by the shell script "testdriver.sh" that is placed under the test/c directory.
Preparation procedure for the automatic test is explained in test/c/testprepare.txt (in Japanese).