Note that this assignment needs to be done quickly so we can work on the final code gen phase assignments!

In this assignment you will compute the scope of each variable and what the address is for the variable. This assignment probably requires about 30 lines of carefully thought out code. Do not try to do it at the last minute because it is tricky!

To do this you will need to start by allowing for your tree node definition to save the size, type of reference, and offset location. You will need to make modifications to the parser, semantic section and the tree print routine. These changes will get your code ready for code generation. The text below combined with what you learned in class will tell you what you will need to do to get this to work.

The results will be that the -P option will now print the location and scope type for each variable and some extra size information at function and compound nodes.

The Parser

If you haven't already you need to record the size of every declared variable at parse time. For local arrays use the constant size + 1 as the size. For all other items, paramers, globals, locals use a size of 1.

The Semantic Analysis Changes

  1. You will need to augment the TreeNode to handle offsets in local variable space and global space for declared variables and the size of the thing to be allocated. How to do this was discussed in class. (Feel free to ask if you want me to go over any or all of it again.) If you remember, you will maintain pointers for the place in global memory and the place in local (frame) memory in two offset variables in the semantic section. You will increment them as you allocate each variable and reset the local memory pointer within each function. The result will be that every declaration that requires space will store the offset of that space and the size in the treenode. A flag for whether the space comes from the global space or local space will also be set. This will of course be used to tell you what offset register to use: 0 or 1 as explained when we discussed the C- memory architecture.

    The offset and size that is used for variables goes unused for all the rest of the nodes accept the function declaration and compound nodes. We will use the size in the function node for storing the initial stack frame size. This can be set on exit of the code generation for the declarations in the function. The offset in function declaration nodes will be used later for storing the starting address of the function so that it can be looked up in the symbol table and we can jump to the various functions.

  2. The symbol table is already used to point to the TreeNodes so you can now find the offset of every reference to a variable when you arrive at them and look them up in the symbol table. You can now copy that information for use in those referencing nodes if you want. (e.g. variables in equations) as well during the tree traversal in the semantic analysis routine.

  3. When you leave the semantic analysis section the symbol table will have been reduced back down to the globals section. If you freed the symbol table before... don't... you should pass symbol table of globals along with the end of the global space to the code generation section as described below! This will be used for doing such things as initially global and static variables.

The code will be testing by comparing the results of doing c- -P on various test programs such as scope3.c- here:

int a;
bool b;
char c;
int aa[11];
bool bb[22];
char cc[33];

main(int pa; bool pb; char pc; int paa[]; bool pbb[]; char pcc[])
    int la;
    bool lb;
    char lc;
    int laa[11];
    bool lbb[22];
    char lcc[33];
        int sla;
        bool slb;
        char slc;
        int slaa[11];
        bool slbb[22];
        char slcc[33];
        int tla;
        bool tlb;
        char tlc;
        int tlaa[11];
        bool tlbb[22];
        char tlcc[33];
        static int sa;
        static bool sb;
        static char sc;
        static int saa[11];
        static bool sbb[22];
        static char scc[33];

fox(int fpa; bool fpb; char fpc; int fpaa[]; bool fpbb[]; char fpcc[])