CPSC 411 - Lab Notes - 02-03 (Code Generation)

The stack machine.

You may download stack.csh and bashstack.sh (updated 02-02) to test your generated code.

Stack machine instructions.

cPUSH <const>
This "pushes" a constant value onto the stack. This may only be an integer. This instruction will normally be generated by factors only.
rPUSH <register>
This "pushes" a register onto the stack. In the code generated for minisculus, you may think of all identifiers as registers. This instruction will be generated by any semantic construction that uses/holds an ID.
sPUSH
Not used.
LOAD <register>
This pops the top value of the stack into the register. Used whenever storing a value into an identifier.
OP2 <op>
op is one of -+*/. This pops the top two elements of the stack and then pushes the result of the second element op the first.
cJUMP <label>
This pops the top of the stack and if it is 0, jumps to the label.
JUMP <label>
Jumps to the label.
PRINT
This pops the top of the stack and prints it.
READ <register>
This reads an integer and puts it into the register.

Code generation

First, we recall the code for the prog class is as follows:


class prog:
      """
      A class that holds a parsed program. Its only data is a statement."""
      def __init__(self,tlist):
            self.stmt = stmt(tlist)

      def gencode(self):
            self.stmt.gencode()

The code for a fragment of the stmt class is :

class stmt:
    
             ...
                  
      def gencode(self):
            if self.type == 'IF':
                  self.expr.gencode()
                  flab=newlabel()
                  endlab=newlabel()
                  print "cJUMP %s"%flab
                  self.tstmt.gencode()
                  print "JUMP %s"%endlab
                  print "%s:"%flab
                  self.fstmt.gencode()
                  print "%s:"%endlab

                 ...

where the ...stands for code that works on other types of statements.

The generation of code should be nothing more than a traversal of your semantic tree, starting at the root (prog) and printing various instructions as needed. Note that since we are recursively generating code, attention must be paid to the order that items are generated in. In the if example, we will be generating code that checks the value of an expression and the conditionally executes one statment or the other. So, we must be able to jump to the false statement when the expression is zero (false) and jump past it if we execute the true statement.

This requires us to generate our labels for the jumps all at the same time. If we don't, the true or false statement may generate other labels, leading to mass confusion. The while and for statements would need to consider this as well.

Last modified by Brett Giles
Last modified: Sat Feb 22 15:12:34 MST 2003

Valid XHTML 1.0!