CS712/CS812
Possible Phase 1 Assignments
Spring 2001


You will be assigned one of the following tasks. Please let me know prior to Monday January 29 any preference you might have. I will give you a definite assignment no later than Wednesday January 31. Most students will be assigned the first task, compiling global declarations, which is the primary goal to be accomplished by this phase. This phase ends on Sunday February 18.

  1. Compile global declarations. Handle pointer and array declarators. You may limit the syntax so that array dimensions must always be given. You may assume the dimension given will always be an unsigned integer constant. You do not need to handle function declarators or abstract declarators. You do not need to handle typedef, but you should handle all other storage class specifiers. You do not need to handle struct types, union types, enum types or typedef names, but you should handle all other type specifiers. You should handle type qualifiers. You should support multiple declarators per declaration. You do not need to handle initializers.

    You should use the "bucket" module to process the type qualifiers, storage class specifiers and type specifiers. The "types" module should be used to represent the type of the declaration. The declared identifier should be installed in the symbol table along with the type, the storage class (if one), and the qualifiers (if any).

    You should also generate Alpha code for declarations that require it. In doing this, two code generation utility functions should be written. The first should evaluate the size of a variable in bytes on the Alpha, given the C type of the variable. The second function should provide the alignment requirements for a variable on the Alpha, given the C type of the variable. The Alpha code to generate will be discussed in class.

    If the declaration does not declare an identifier, it is an error. Are there any other semantic errors that need to be reported?

  2. Provide support for typedef. Typedef is a very tricky feature to implement because its syntax is not LALR (i.e. cannot be handled directly by yacc/bison). See Section 5.10 of Harbison and Steele.

    A global variable must be utilized that turns on and off special processing in the scanner. The hard part is deciding when to set and clear this global variable.

    In addition to the coding and testing, this assignment will require you to discuss in class both the typedef "problem" and your solution. Most probably this will happen later in the semester, after this phase is complete.

  3. Test, and repair when necessary, the scanner to be sure it properly handles all types of constants: integer, floating-point, character and string. Also make sure that our scanner will work with the available C preprocessors. (Usually C preprocessors leave some # control lines in the output which will need to be removed by our scanner.) Finally, remove any unnecessary code from our scanner.

    A big issue that must be decided is how to internally represent the constant values. Should we keep them as strings or convert them to their "native" formats? If we convert them, are there portability issues? (We would like to restrict all machine-specific code to the code generator.) You will be expected to lead the discussion on making these decisions.

    A second concern is to do the necessary semantic checking. In particular, does a given constant value fit in their designated type on the target machine? And, again, how do we implement this in a portable way?

  4. Provide basic support for building Abstract Syntax Trees for expressions and statements. The key task is to design the AST data structure and to get class consensus that your approach is the right one. This will require that you outline your ideas in class and ask for feedback. Appropriate documentation of your design (in the header file) will be important.

    Then you will write actions to build trees for all the syntax rules for expressions and statements. Note that you are not doing semantic analysis, but rather you are simply building "raw" trees with many fields (e.g. type) not yet filled in. Allocation of tree nodes should be made from an expandable pool, which will allow all previously allocated trees to be re-claimed by simply re-setting the pool. You also need to write a debugging routine that will display a tree in human-readable form (perhaps one tree node per line).

  5. Modify an existing register allocator for the MIPS 2000/3000 processor to create one for the Alpha processor. Document and test the new register allocator. The MIPS register allocator is available in ~cs712/public/mips-regalloc.

  6. Write support routines for the semantic analysis to be performed during phase 2 (and later). In particular design routines to implement the "integral promotions" (ANSI C, section 3.2.1.1), the "usual arithmetic conversions" (ANSI C, section 3.2.1.5), and the "default argument promotions" (ANSI C, section 3.3.2.2). These routines will be passed AST trees as parameters and will possibly add conversion nodes to the tops of the trees according to the ANSI C rules. The interface for the routine implementing the "usual arithmetic conversions" may be a bit tricky as it will take two input trees and both trees might be modified, so a mechanism for returning two values must be provided.

    In addition, write two routines that will check whether a tree denotes an "lvalue" or a "modifiable lvalue" (ANSI C, section 3.2.2.1). Conceptually these functions return a Boolean value, either true or false.

    Harbison and Steele is a good reference for this task. See section 6.3 for information about conversions. Section 7.1.1 has a concise discussion of lvalues.

The code for a "skeleton" scanner, a "skeleton" parser, the "bucket" module, the "message" module, the symbol table, and the "types" module can be found in ~cs712/public/pcc3. This directory also contains a Makefile. Note that the compiler will read from stdin and write to stdout.


Last modified on January 23, 2001.

Comments and questions should be directed to pjh@cs.unh.edu