|
UGAVAC Code Patterns for µ-PascalThis document contains the code patterns for the undergraduate version
of Micro Pascal.
Expressions:
Assumption: the code for an expression is generated in such a way
that if the expression has an l-value, the l-value is
placed on top of the stack; otherwise the r-value is
left on top of the stack.
Factor:
* numeric constant 'pushc[I|R] <const_value>'
* string constant 'pushs <string text>'
* variable or formal param passed by value
- local 'pusha <offset>'
- non-local 'pushga <lev-diff>, <offset>'
* formal parameter passed by reference
- local 'pushI <offset>'
- non-local 'pushgI <lev-diff>, <offset>'
* (expression)
--------------
| expression |
| code |
--------------
Term:
* just one factor
--------------
| factor |
| code |
--------------
* factor * factor -- See Note 8)
--------------
| factor code |
| (left arg) |
--------------
'fetch[I|R]' --- See Note 1)
--------------
| factor code |
| (right arg) |
--------------
'fetch[I|R]' --- See Note 1)
'mul[I|R]'
* factor / factor -- See Note 8)
--------------
| factor code |
| (left arg) |
--------------
'fetch[I|R]' --- See Note 1)
--------------
| factor code |
| (right arg) |
--------------
'fetch[I|R]' --- See Note 1)
'divR'
* factor div factor -- See Note 8)
--------------
| factor code |
| (left arg) |
--------------
'fetch[I|R]' --- See Note 1)
--------------
| factor code |
| (right arg) |
--------------
'fetch[I|R]' --- See Note 1)
'divI'
Simple_Expression:
* just one term
--------------
| term code |
| |
--------------
* + term
--------------
| term code |
| |
--------------
'fetch[I|R]' --- See Note 1)
* - term
--------------
| term code |
| |
--------------
'fetch[I|R]' --- See Note 1)
'neg[I|R]'
* term + term
--------------
| term code |
| (left arg) |
--------------
'fetch[I|R]' --- See Note 1)
--------------
| term code |
| (right arg) |
--------------
'fetch[I|R]' --- See Note 1)
'add[I|R]'
* term - term
--------------
| term code |
| (left arg) |
--------------
'fetch[I|R]' --- See Note 1)
--------------
| term code |
| (right arg) |
--------------
'fetch[I|R]' --- See Note 1)
'sub[I|R]'
Expression:
* just a simple_expr
--------------
| simple expr |
| code |
--------------
* simple_expr < simple_expr (<=, =, <>, >=, and > are similar)
--------------
| simple expr |
| (left arg) |
--------------
'fetch[I|R]' --- See Note 1)
--------------
| simple expr |
| (right arg) |
--------------
'fetch[I|R]' --- See Note 1)
'lt[I|R]'
Similar code for other relops.
Statement:
* empty -- no code is generated
* assignment: lhs := expression
lhs is:
- local variable or param passed by value
--------------
| expression |
| code |
--------------
'fetch[I|R]' --- See Note 1)
'flt' --- See Note 6)
'pop[I|R] <offset>'
- non-local variable or param passed by value
--------------
| expression |
| code |
--------------
'fetch[I|R]' --- See Note 1)
'flt' --- See Note 6)
'popg[I|R] <lev-diff>, <offset>'
- local formal parameter passed by ref
'pushI <offset>'
--------------
| expression |
| code |
--------------
'fetch[I|R]' --- See Note 1)
'flt' --- See Note 6)
'popi[I|R]'
- non-local formal parameter passed by ref
'pushgI <lev-diff>, <offset>'
--------------
| expression |
| code |
--------------
'fetch[I|R]' --- See Note 1)
'flt' --- See Note 6)
'popi[I|R]'
* User-defined procedure call:
no parameters:
procname
'enter <callerLev-calledLev+1>'
'call <entrypoint>, 0'
--- See Note 2)
with parameters:
procname( expression-1, ..., expression-n )
'enter <callerLev-calledLev+1>'
----------------
| expression-1 |
| code |
----------------
'fetch[I|R]' --- See Note 9)
'flt' --- See Note 7)
...
...
----------------
| expression-n |
| code |
----------------
'fetch[I|R]' --- See Note 9)
'flt' --- See Note 7)
'call <entrypoint>, <# of params>'
--- See Note 2)
* External I/O procedure call:
see the UGAVAC handout (iolib library)
* conditional (IF):
if expression then statement
--------------
| expression |
| code |
-------------- -- See Note 3)
'jumpz <end-label>'
--------------
| statement |
| code |
--------------
'<end-label>' --- See Note 4)
if expression then statement-1
else statement-2
--------------
| expression |
| code |
--------------
'jumpz <else-label>'
--------------
| statement-1 |
| code |
--------------
'jump <end-label>'
'<else-label>'
--------------
| statement-2 |
| code |
--------------
'<end-label>'
* WHILE loop:
while expression do statement
'<label>'
--------------
| expression |
| code |
--------------
'jumpz <end-label>'
--------------
| statement |
| code |
--------------
'jump <label>'
'<end-label>'
* REPEAT loop:
repeat stat_list until expression
'<label>'
--------------
| stat_list |
| code |
--------------
--------------
| expression |
| code |
--------------
'jumpz <label>'
* compund statetement:
begin stat_list end -- that is
begin stat-1; stat-2; ... stat-n end
--------------
| stat-1 |
| code |
--------------
--------------
| stat-2 |
| code |
--------------
....
....
--------------
| stat-n |
| code |
--------------
Procedures and the main program
* body of a procedure procedure procname( params );
[decls]
begin
stat_list
end;
'$procname<N>'
'alloc <# of required locations>'
-------------- --- See Note 5)
| stat_list |
| code |
--------------
'return'
* body of the main program: program name;
[decls]
begin
stat_list
end.
'main'
'enter 0'
'alloc <# of required words>'
--------------
| stat_list |
| code |
--------------
'return'
NOTES:
1) The fetch instruction should be used only if the preceding
expression had the l-value, in which case the corresponding
r-value must be fetched.
2) <entrypoint>'s, i.e. entry points (labels) to procedures
must be unique! Hint: Generate an <entrypoint> to be of the
form $funcname<number>, where <number> is a unique (among all
procedures) integer. But remember about the 10 char length limit.
3) Note that the IF, WHILE, and REPEAT statements require a
relational expression. Therefore, since such an expression
does not have the l-value, no fetch instruction is needed.
4) Labels must be unique! Hint: generate a label name to
be of the form '$<number>'.
5) The alloc instruction must allocate the required number of words of
memory for the local variables (do not count parameters).
6) In all assignment statements the type of lhs must be
compatible with the type of the expression. If different
numeric types, use flt if needed, before a pop.
Obvioulsy, cannot assign a real expression to an integer
variable.
7) flt instruction should be used if a conversion of the actual
parameter type to conform to the formal parameter type (int->float)
is required. Note that this is possible for parameters passed
by value only.
8) For all binary numeric operators, operands should have the same
(numeric) types. This may require the use of flt, or
fltb instruction. Note that real is never converted to an int.
For example,
for the expression: 2 + 3.1
generated code should be:
pushcI 2
pushcR 3.1
fltb
addR
for the expression: 2.1 + 3
generated code should be:
pushcR 2.1
pushcI 3
flt
addR
Note that you will know if conversion is necessary only *after*
parsing and generating code for 1st and 2nd argument, and right
before generating the operator code.
Also, the / (division) operator always produces a real result, therefore
even if both operands are of integer type, they must be converted to
real before the divR opration is performed.
9) The fetch instruction is needed if the corresponding expression
has the l-value *and* the parameter is passed by value.
|