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.
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 |
if
statement:
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.
When generating code for an expression, remember that an expression is different from a statement in that it always yields some value.