@Override
    public int[] generate(ArrayList<Function> program) throws Exception {
        // the last function should be main
        if(!program.get(program.size() - 1).name.getString().equals("__MAIN__")) {
            throw new Exception("Main not found");
        }

        // first instructions will be setting the stack pointer and
        // frame pointer to point past the program code
        // will need to be fixed up once the code size is known
        emit(DLX.assemble(DLX.ADDI, sp, zero, 0));
        // fp <- sp
        emit(DLX.assemble(DLX.ADD, fp, zero, sp));

        boolean main = true;    // first function will be main
        for(int i = program.size() - 1; i >= 0; i--) {
            Function f = program.get(i);
            currentFunction = f;
            makeLabel(f.name);

            // see what registers will be saved and how many memory cells will be needed
            AnalyzeRegistersUsed analysis = new AnalyzeRegistersUsed(registersAvailable, retAddr - minAvail);
            f.entryPoint.runPass(analysis);
            f.locals.allocateMemoryCells(analysis.memNeeded);

            // clear the record of registers pushed onto stack from previous function
            regStack.clear();

            // set up stack frame for local variables
            if(!main) {
                push(fp);
                // fp <- sp
                emit(DLX.assemble(DLX.ADD, fp, zero, sp));
            }
            if(f.locals.getSize() > 0) {
                emit(DLX.assemble(DLX.ADDI, sp, sp, f.locals.getSize()));
            }

            if(!main) {
                // save registers onto stack
                for(Integer reg : analysis.registersUsed) {
                    int realReg = reg + minAvail;
                    regStack.push(realReg); // keep track of order registers are pushed
                    push(realReg);
                }
            }

            // emit code for the function body
            emitCode(f.entryPoint);
            main = false;       // after the first function, it's not main
        }

        // code for all functions has been generated, check if there
        // are unresolved labels
        if(!fixup.isEmpty()) {
            throw new Exception("Unresolved branch location");
        }

        // fix the first instruction now that the size of the text is
        // known.
        int spSet = code.get(0);
        spSet = setC(spSet, 4 * code.size());
        code.set(0, spSet);
        // copy the code into an int array
        int[] rval = new int[code.size()];
        for(int i = 0; i < code.size(); i++) {
            rval[i] = code.get(i);
        }
        // clear code in case we use this object to generate code for
        // multiple programs
        code.clear();
        return rval;
    }