WISC C-- Compiler

This is a C-- compiler that targets MIPS and WISC assembly language. C-- is C with some stuff removed. C-- supports the types int and bool (no floats or chars).

Things from C which C-- does not have:

Note: += -= *= /= are all implemented but do not have the correct semantics. a += b just expands into a = a + b which is fine if a and b are simple expressions, but they are different from C when a involves a function like "*func() += b;" func() in this case will be evaluated twice.

Everything else should be valid C-- (including pointers to ints and bool) ex: this is a valid function

int **func(int *a, int **b, int size) {
  int i;
  i = 0;
  while (i < size) {
    b[i] = NULL;
    i = i + 1;
  }
  return b;
}
int **func2(int *a, int **b) {
  while (*b != NULL) {
    *b = a + 14;
    b = b + 1;
  }
  return b;
}

Allocating data on the heap. The C-- compiler generates a function "void *sbrk(int length);" which will return a pointer to a segment of memory length long. For MIPS, it gets space through the sbrk system call. For WISC, it just uses the space directly after all the code. A memory manager that maintains a list of free blocks can be implemented on top of this, providing the standard malloc() and free().

Input/Output is expressed like
cout << "This is cool\n";
cin >> x;
cout << x + 2;
cin >> y[15];

These are not streams like in C++, the format must be "cout << some expression" or "cin >> some variable". When exporting to WISC, the read statements are just ignored and write statements use the wrint and wrch instructions.

The WISC architecture implements multiplication and division by exporting two functions (in wisc.java) that carry out the operation. They are really slow! They take the numbers to multiply or divide in $v0 and $v1 and return the result in $6. divide returns the result in $6 and the remainder in $t0. (used by the % modulo operator)


Test Programs


Running the compiler

To run the compiler, you can either download the cmm.jar file or if you are working in the CS computer labs you can add the following line to .cshrc.local

setenv CLASSPATH ".:/s/java/jre/lib/rt.jar:/u/l/e/lenz/public/cmm.jar"
Once your classpath is set up (by either restarting the shell or executing "source .cshrc.local"), you can run the compiler to output WISC assembly language
% java cmm <input.C> <output.s>
% wiscas <output.s>
% wisc-emulator <output.mem>
and to export MIPS assembly language (runnable in spim).
% java cmm --mips <input.C> <output.s>
% spim -file <output.s>
Spim can be found at http://www.cs.wisc.edu/~larus/spim.html.

Compiling and modifing the compiler

Source: wisc-compiler.tar.gz

To compile the compiler you will need Java CUP and JLex installed in the CLASSPATH. I suggest you include the runtime classes in the cmm.jar file. Then Java CUP and JLex don't need to be on the CLASSPATH to run the compiler.

Files:

To make changes to the exported WISC assembly language, you will need to look in ast.java, expressions.java, statements.java and Codegen.java. There is a boolean stored in the Codegen class which gets set based on the command line param, so in ast.java there is code that looks like

if (Codegen.Wisc) {
  /* generate wisc assembly */
  Codegen.generate(..);
  ..
} else {
  /* generate MIPS assembly */
  Codegen.generate(..);
}

A lot of the exported code is the same so no checking is even done. Expressions are evaluated with a simple stack approach. Arguments are pushed onto the stack and operators pop them off. Branching uses a Control-Flow Code approach. There is a small optimization: when a push is followed immediatly by a pop, both are removed and a move instruction is added if the registers are different. The stack starts at FFFF and grows downward. The AR for each function contains, from top to bottom: params, return address, control link, local vars.


Comments, bugs, etc can be mailed to jelenz@wisc.edu
Last Updated: Thursday Feb 19, 2003