This document provides an overview of the code generation steps required to complete the backend for your Source language compiler. The annotated grammar below adds references to code generation actions in blue that describe what code should be emitted for the given language construct.

See the lecture slides for details on the Machine architecture and instruction set.

Annotated grammar

program: CGtopBegin bareScope CGtopEnd # program top-level

bareScope: declarations # only declarations
scope: { bareScope } # scope enclosed with braces
| declarations statements # both declarations and statements
| statements # only statements

declarations: var variableNames compoundType # declare variables
| func procedureName ( ) CGroutinePrologue scope CGroutineEpilogue CGemitRoutine
| func procedureName ( parameters ) CGroutinePrologue scope CGroutineEpilogue CGemitRoutine
| func functionName ( ) scalarType CGroutinePrologue scope CGroutineEpilogue CGemitRoutine
| func functionName ( parameters ) scalarType CGroutinePrologue scope CGroutineEpilogue CGemitRoutine
| declarations declarations> # sequence of declarations

variableNames: variableName
| variableNames , variableNames # comma separated sequence of variable names

scalarType: integer # integer type
| boolean # Boolean type

compoundType: scalarType
| [ bound ] scalarType # 1-dimensional array type
| [ bound ] [ bound ] scalarType # 2-dimensional array type

bound: integer # array of length integer

parameters: parameterNames scalarType # declare one or more formal parameters
| parameters , parameters # sequence of formal parameters

parameterNames: parameterName
| parameterNames , parameterNames # comma separated sequence of parameter names

| { } # empty scope

statements: variable = expression CGassign # assignment
| if expression CGifBranch scope CGifEnd # conditional statement
| if expression CGifBranch scope CGifEnd elseIfArms
| if expression CGifBranch scope CGifEnd else scope
| if expression CGifBranch scope CGifEnd elseIfArms else scope
| while expression CGwhileBranch scope CGwhileTop # loop while expression is true
| repeat scope until expression CGrepeatLoop # loop until expression is true
| break CGbreak # exit out of enclosing loop
| break integer CGbreak # exit out of multiple enclosing loops
| return ( expression ) CGreturnSave CGroutineEnd # return from a function
| return CGroutineEnd # return from a procedure
| print outputs # print to standard output
| input inputs # input from standard input
| procedureName ( ) CGprocCall # procedure call (no arguments)
| procedureName ( arguments ) CGprocCall # procedure call (with arguments)
| scope # nested scope
| statements statements # sequence of statements

elseIfArms: else if expression CGifBranch scope CGifEnd # else-if arm
| elseIfArms elseIfArms # sequence of else-if arms

arguments: expression CGsaveArg
| arguments , arguments # comma separated sequence of arguments

outputs: expression CGprintExpr # integer or Boolean expression value to be printed
| text CGprintText # string constant to be printed
| newline CGprintNewline # print newline
| outputs , outputs # sequence of output arguments

inputs: variable CGreadInteger CGassign # input to this integer variable
| inputs , inputs # input sequence

variable: variableName CGnameAddr # reference to scalar variable
| arrayName CGnameAddr [ expression CGarrOffset ] # reference to 1-dimensional array element
| arrayName CGnameAddr [ expression CGarrOffset ] [ expression CGarrOffset ] # reference to 2-dimensional array element

expression: integer CGconst # literal integer constant
| - expression CGneg # unary minus
| expression + expression CGadd # addition
| expression - expression CGsub # subtraction
| expression * expression CGmul # multiplication
| expression / expression CGdiv # integer division
| true CGconst # Boolean constant true
| false CGconst # Boolean constant false
| not expression CGnot # Boolean not
| expression CGshortCircuitFalse and expression # Conditional Boolean and
| expression CGshortCircuitTrue or expression # Conditional Boolean or
| expression = expression CGeq # equality comparison
| expression != expression CGneq # inequality comparison
| expression < expression CGlt # less-than comparison
| expression <= expression CGlte # less-than-or-equal comparison
| expression > expression CGgt # greater-than comparison
| expression >= expression CGgte # greater-than-or-equal comparison
| ( expression )
| ( expression1 if expression2 else expression3 ) CGternaryIf # Python-style ternary conditional expression
| variable CGretrieve # reference to local variable
| functionName ( ) CGfuncCall # function call (no arguments)
| functionName ( arguments ) CGfuncCall # function call (with arguments)
| parameterName CGnameAddr CGretrieve # reference to a formal parameter

variableName: identifier
arrayName: identifier
functionName: identifier
parameterName: identifier
procedureName: identifier

Code generation actions

Program, Major Scopes & Routines

Statements

Variable addressing

You must distinguish between the address and the value of a particular name. The address is a location on the stack (within an activation record) where the name lives, and the value is the machine word that is stored at that address. For arrayName's, the address of the name is also the address where the first element is stored.

Expressions

When generating code for an expression, remember that an expression is different from a statement in that it always yields some value.