408 lines
8.3 KiB
Plaintext
408 lines
8.3 KiB
Plaintext
.sp 1.5i
|
|
.de CL
|
|
.ft R
|
|
c\\$1
|
|
.ft 5
|
|
\fIcode statement-\\$1
|
|
.ft 5
|
|
\fBbra *\fRexit_label
|
|
.ft 5
|
|
..
|
|
.NH
|
|
Translation of Pascal to EM code
|
|
.nh
|
|
.LP
|
|
.sp
|
|
A short description of the translation of Pascal constructs to EM code is
|
|
given in the following paragraphs. The EM instructions and Pascal terminal
|
|
symbols are printed in \fBboldface\fR. A sentence in \fIitalics\fR is a
|
|
description of a group of EM (pseudo)instructions.
|
|
.sp
|
|
.NH 2
|
|
Global Variables
|
|
.LP
|
|
.sp
|
|
For every global variable, a \fBbss\fR block is reserved. To enhance the
|
|
readability of the EM-code generated, the variable-identifier is used as
|
|
a data label to address the block.
|
|
.sp
|
|
.NH 2
|
|
Expressions
|
|
.LP
|
|
.sp
|
|
Operands are always evaluated, so the execution of
|
|
.br
|
|
.ti +3m
|
|
\fBif\fR ( p <> nil ) \fBand\fR ( p^.value <> 0 ) \fBthen\fR .....
|
|
.br
|
|
might cause a run-time error, if p is equal to nil.
|
|
.LP
|
|
The left-hand operand of a dyadic operator is almost always evaluated before
|
|
the right-hand side. Peculiar evaluations exist for the following cases:
|
|
.sp
|
|
the expression: set1 <= set2, is evaluated as follows :
|
|
.nf
|
|
- evaluate set2
|
|
- evaluate set1
|
|
- compute set2+set1
|
|
- test set2 and set2+set1 for equality
|
|
.fi
|
|
.sp
|
|
the expression: set1 >= set2, is evaluated as follows :
|
|
.nf
|
|
- evaluate set1
|
|
- evaluate set2
|
|
- compute set1+set2
|
|
- test set1 and set1+set2 for equality
|
|
.fi
|
|
.sp
|
|
Where allowed, according to the standard, constant integral expressions are
|
|
compile-time evaluated while an effort is made to report overflow on target
|
|
machine basis. The integral expressions are evaluated in the type \fIarith\fR.
|
|
The size of an arith is assumed to be at least the size of the integer type
|
|
on the target machine. If the target machine's integer size is less than the
|
|
size of an arith, overflow can be detected at compile-time. However, the
|
|
following call to the standard procedure new, \fInew(p, 3+5)\fR, is illegal,
|
|
because the second parameter is not a constant according to the grammar.
|
|
.sp
|
|
Constant floating expressions are not compile-time evaluated, because the
|
|
precision on the target machine and the precision on the machine on which the
|
|
compiler runs could be different. The boolean expression \fI(1.0 + 1.0) = 2.0\fR
|
|
could evaluate to false.
|
|
.sp
|
|
.NH 2
|
|
Statements
|
|
.NH 3
|
|
Assignment Statement
|
|
|
|
\fRPASCAL :
|
|
.ti +3m
|
|
\f5(variable-access | function-identifier) \fB:=\f5 expression
|
|
|
|
\fREM :
|
|
.nf
|
|
.in +3m
|
|
.ft I
|
|
evaluate expression
|
|
store in variable-access or function-identifier
|
|
.ft R
|
|
.in -3m
|
|
.fi
|
|
|
|
In case of a function-identifier, a hidden temporary variable is used to
|
|
keep the function result.
|
|
.bp
|
|
.NH 3
|
|
Goto Statement
|
|
|
|
\fRPASCAL :
|
|
.ti +3m
|
|
\fBGOTO\f5 label
|
|
|
|
\fREM :
|
|
.in +3m
|
|
Two cases can be distinguished :
|
|
.br
|
|
- local goto,
|
|
.ti +2m
|
|
in which a \fBbra\fR is generated.
|
|
|
|
- non-local goto,
|
|
.in +2m
|
|
.ll -1i
|
|
a goto_descriptor is build, containing the ProgramCounter of the instruction
|
|
jumped to and an offset in the target procedure frame which contains the
|
|
value of the StackPointer after the jump. The code for the jump itself is to
|
|
load the address of the goto_descriptor, followed by a push of the LocalBase
|
|
of the target procedure and a \fBcal\fR $_gto. A message is generated to
|
|
indicate that a procedure or function contains a statement which is the
|
|
target of a non-local goto.
|
|
.ll +1i
|
|
.in -2m
|
|
.in -3m
|
|
.sp 2
|
|
.NH 3
|
|
If Statement
|
|
|
|
\fRPASCAL :
|
|
.in +3m
|
|
.ft 5
|
|
\fBIF\f5 boolean-expression \fBTHEN\f5 statement
|
|
|
|
.in -3m
|
|
\fREM :
|
|
.nf
|
|
.in +3m
|
|
\fIevaluation boolean-expression
|
|
\fBzeq \fR*exit_label
|
|
\fIcode statement
|
|
\fRexit_label
|
|
.in -3m
|
|
.fi
|
|
.sp 2
|
|
\fRPASCAL :
|
|
.in +3m
|
|
.ft 5
|
|
\fBIF\f5 boolean-expression \fBTHEN\f5 statement-1 \fBELSE\f5 statement-2
|
|
|
|
.in -3m
|
|
\fREM :
|
|
.nf
|
|
.in +3m
|
|
\fIevaluation boolean-expression
|
|
\fBzeq \fR*else_label
|
|
\fIcode statement-1
|
|
\fBbra \fR*exit_label
|
|
\fRelse_label
|
|
\fIcode statement-2
|
|
\fRexit_label
|
|
.in -3m
|
|
.fi
|
|
.sp 2
|
|
.NH 3
|
|
Repeat Statement
|
|
|
|
\fRPASCAL :
|
|
.in +3m
|
|
.ft 5
|
|
\fBREPEAT\f5 statement-sequence \fBUNTIL\f5 boolean-expression
|
|
|
|
.in -3m
|
|
\fREM :
|
|
.nf
|
|
.in +3m
|
|
\fRrepeat_label
|
|
\fIcode statement-sequence
|
|
\fIevaluation boolean-expression
|
|
\fBzeq\fR *repeat_label
|
|
.in -3m
|
|
.fi
|
|
.bp
|
|
.NH 3
|
|
While Statement
|
|
|
|
\fRPASCAL :
|
|
.in +3m
|
|
.ft 5
|
|
\fBWHILE\f5 boolean-expression \fBDO\f5 statement
|
|
|
|
.in -3m
|
|
\fREM :
|
|
.nf
|
|
.in +3m
|
|
\fRwhile_label
|
|
\fIevaluation boolean-expression
|
|
\fBzeq\fR *exit_label
|
|
\fIcode statement
|
|
\fBbra\fR *while_label
|
|
\fRexit_label
|
|
.in -3m
|
|
.fi
|
|
.sp 2
|
|
.NH 3
|
|
Case Statement
|
|
.LP
|
|
.sp
|
|
The case-statement is implemented using the \fBcsa\fR and \fBcsb\fR
|
|
instructions.
|
|
|
|
\fRPASCAL :
|
|
.in +3m
|
|
\fBCASE\f5 case-expression \fBOF\f5
|
|
.in +5m
|
|
case-constant-list-1 \fB:\f5 statement-1 \fB;\f5
|
|
.br
|
|
case-constant-list-2 \fB:\f5 statement-2 \fB;\f5
|
|
.br
|
|
\&.
|
|
.br
|
|
\&.
|
|
.br
|
|
case-constant-list-n \fB:\f5 statement-n [\fB;\f5]
|
|
.in -5m
|
|
\fBEND\fR
|
|
.in -3m
|
|
.sp 2
|
|
.LP
|
|
.ll -1i
|
|
The \fBcsa\fR instruction is used if the range of the case-expression
|
|
value is dense, i.e.
|
|
.br
|
|
.ti +3m
|
|
\f5( upperbound \- lowerbound ) / number_of_cases\fR
|
|
.br
|
|
is less than the constant DENSITY, defined in the file \fIdensity.h\fR.
|
|
|
|
If the range is sparse, a \fBcsb\fR instruction is used.
|
|
|
|
.ll +1i
|
|
\fREM :
|
|
.nf
|
|
.in +3m
|
|
\fIevaluation case-expression
|
|
\fBbra\fR *l1
|
|
.CL 1
|
|
.CL 2
|
|
.
|
|
.
|
|
.CL n
|
|
.ft R
|
|
\&.case_descriptor
|
|
.ft 5
|
|
\fIgeneration case_descriptor
|
|
\fRl1
|
|
.ft 5
|
|
\fBlae\fR .case_descriptor
|
|
.ft 5
|
|
\fBcsa\fR size of (case-expression)
|
|
\fRexit_label
|
|
.in -3m
|
|
.fi
|
|
.bp
|
|
.NH 3
|
|
For Statement
|
|
|
|
\fRPASCAL :
|
|
.in +3m
|
|
.ft 5
|
|
\fBFOR\f5 control-variable \fB:=\f5 initial-value (\fBTO\f5 | \fBDOWNTO\f5) final-value \fBDO\f5 statement
|
|
|
|
.ft R
|
|
.in -3m
|
|
The initial-value and final-value are evaluated at the beginning of the loop.
|
|
If the values are not constant, they are evaluated once and stored in a
|
|
temporary.
|
|
|
|
EM :
|
|
.nf
|
|
.in +3m
|
|
\fIload initial-value
|
|
\fIload final-value
|
|
\fBbgt\fR exit-label (* DOWNTO : \fBblt\fI exit-label\fR *)
|
|
\fIload initial-value
|
|
\fRl1
|
|
\fIstore in control-variable
|
|
\fIcode statement
|
|
\fIload control-variable
|
|
\fBdup\fI control-variable
|
|
\fIload final-value
|
|
\fBbeq\fR exit_label
|
|
\fBinc\fI control-variable\fR (* DOWNTO : \fBdec\fI control-variable\fR *)
|
|
\fBbra *\fRl1
|
|
\fRexit_label
|
|
.in -3m
|
|
.fi
|
|
|
|
Note: testing must be done before incrementing(decrementing) the
|
|
control-variable,
|
|
.br
|
|
\h'\w'Note: 'u'because wraparound could occur, which could lead to an infinite
|
|
loop.
|
|
.sp 2
|
|
.NH 3
|
|
With Statement
|
|
|
|
\fRPASCAL :
|
|
.ti +3m
|
|
\fBWITH\f5 record-variable-list \fBDO\f5 statement
|
|
|
|
.ft R
|
|
The statement
|
|
.ti +3m
|
|
\fBWITH\fR r\s-3\d1\u\s0, r\s-3\d2\u\s0, ..., r\s-3\dn\u\s0 \fBDO\f5 statement
|
|
|
|
.ft R
|
|
is equivalent to
|
|
.in +3m
|
|
\fBWITH\fR r\s-3\d1\u\s0 \fBDO\fR
|
|
\fBWITH\fR r\s-3\d2\u\s0 \fBDO\fR
|
|
...
|
|
\fBWITH\fR r\s-3\dn\u\s0 \fBDO\f5 statement
|
|
|
|
.ft R
|
|
.in -3m
|
|
The translation of
|
|
.ti +3m
|
|
\fBWITH\fR r\s-3\d1\u\s0 \fBDO\f5 statement
|
|
.br
|
|
.ft R
|
|
is
|
|
.nf
|
|
.in +3m
|
|
\fIpush address of r\s-3\d1\u\s0
|
|
\fIstore address in temporary
|
|
\fIcode statement
|
|
.in -3m
|
|
.fi
|
|
|
|
.ft R
|
|
An occurrence of a field is translated into:
|
|
.in +3m
|
|
\fIload temporary
|
|
.br
|
|
\fIadd field-offset
|
|
.in -3m
|
|
.bp
|
|
.NH 2
|
|
Procedure and Function Calls
|
|
|
|
.ft R
|
|
In general, the call
|
|
.ti +5m
|
|
p(a\s-3\d1\u\s0, a\s-3\d2\u\s0, ...., a\s-3\dn\u\s0)
|
|
.br
|
|
is translated into the sequence:
|
|
|
|
.in +5m
|
|
.nf
|
|
\fIevaluate a\s-3\dn\u\s0
|
|
\&.
|
|
\&.
|
|
\fIevaluate a\s-3\d2\u\s0
|
|
\fIevaluate a\s-3\d1\u\s0
|
|
\fIpush localbase
|
|
\fBcal\fR $p
|
|
\fIpop parameters
|
|
.ft R
|
|
.fi
|
|
.in -5m
|
|
|
|
i.e. the order of evaluation and binding of the actual-parameters is from
|
|
right to left. In general, a copy of the actual-parameter is made when the
|
|
formal-parameter is a value-parameter. If the formal-parameter is a
|
|
variable-parameter, a pointer to the actual-parameter is pushed.
|
|
|
|
In case of a function call, a \fBlfr\fR is generated, which pushes the
|
|
function result on top of the stack.
|
|
.sp 2
|
|
.NH 2
|
|
Register Messages
|
|
|
|
.ft R
|
|
A register message can be generated to indicate that a local variable is never
|
|
referenced indirectly. This implies that a register can be used for a variable.
|
|
We distinguish the following classes, given in decreasing priority:
|
|
|
|
\(bu control-variable and final-value of a for-statement
|
|
.br
|
|
.ti +5m
|
|
to speed up testing, and execution of the body of the for-statement
|
|
.sp
|
|
\(bu record-variable of a with-statement
|
|
.br
|
|
.ti +5m
|
|
to improve the field selection of a record
|
|
.sp
|
|
\(bu remaining local variables and parameters
|
|
.sp 2
|
|
.NH 2
|
|
Compile-time optimizations
|
|
|
|
.ft R
|
|
The only optimization that is performed is the evaluation of constant
|
|
integral expressions. The optimization of constructs like
|
|
.ti +5m
|
|
\fBif\f5 false \fBthen\f5 statement\fR,
|
|
.br
|
|
is left to either the peephole optimizer, or a global optimizer.
|