|
@@ -7689,7 +7689,7 @@ $\Atm$ to x86:
|
|
|
\]
|
|
|
\fi}
|
|
|
\end{tcolorbox}
|
|
|
-\caption{The abstract syntax of \LangXIf{} (extends \LangXInt{} of figure~\ref{fig:x86-int-ast}).}
|
|
|
+\caption{The abstract syntax of \LangXIf{} (extends \LangXInt{} shown in figure~\ref{fig:x86-int-ast}).}
|
|
|
\label{fig:x86-1}
|
|
|
\end{figure}
|
|
|
|
|
@@ -7703,15 +7703,15 @@ $x < y$, then write \code{cmpq} $y$\code{,} $x$. The result of
|
|
|
\key{cmpq} is placed in the special EFLAGS register. This register
|
|
|
cannot be accessed directly, but it can be queried by a number of
|
|
|
instructions, including the \key{set} instruction. The instruction
|
|
|
-$\key{set}cc~d$ puts a \key{1} or \key{0} into the destination $d$
|
|
|
+$\key{set}cc~d$ puts a \key{1} or \key{0} into the destination $d$,
|
|
|
depending on whether the contents of the EFLAGS register matches the
|
|
|
condition code \itm{cc}: \key{e} for equal, \key{l} for less, \key{le}
|
|
|
for less-or-equal, \key{g} for greater, \key{ge} for greater-or-equal.
|
|
|
The \key{set} instruction has a quirk in that its destination argument
|
|
|
-must be single byte register, such as \code{al} (L for lower bits) or
|
|
|
-\code{ah} (H for higher bits), which are part of the \code{rax}
|
|
|
+must be single-byte register, such as \code{al} (\code{l} for lower bits) or
|
|
|
+\code{ah} (\code{h} for higher bits), which are part of the \code{rax}
|
|
|
register. Thankfully, the \key{movzbq} instruction can be used to
|
|
|
-move from a single byte register to a normal 64-bit register. The
|
|
|
+move from a single-byte register to a normal 64-bit register. The
|
|
|
abstract syntax for the \code{set} instruction differs from the
|
|
|
concrete syntax in that it separates the instruction name from the
|
|
|
condition code.
|
|
@@ -7727,9 +7727,9 @@ condition code.
|
|
|
compilation of \key{if} expressions.}
|
|
|
%
|
|
|
The instruction $\key{j}\itm{cc}~\itm{label}$ updates the program
|
|
|
-counter to point to the instruction after \itm{label} depending on
|
|
|
+counter to point to the instruction after \itm{label}, depending on
|
|
|
whether the result in the EFLAGS register matches the condition code
|
|
|
-\itm{cc}, otherwise the jump instruction falls through to the next
|
|
|
+\itm{cc}; otherwise, the jump instruction falls through to the next
|
|
|
instruction. Like the abstract syntax for \code{set}, the abstract
|
|
|
syntax for conditional jump separates the instruction name from the
|
|
|
condition code. For example, \JMPIF{\QUOTE{\code{le}}}{\QUOTE{\code{foo}}}
|
|
@@ -7748,11 +7748,11 @@ are expressible using \code{if} as follows.
|
|
|
\CAND{e_1}{e_2} & \quad \Rightarrow \quad \CIF{e_1}{e_2}{\FALSE{}}\\
|
|
|
\COR{e_1}{e_2} & \quad \Rightarrow \quad \CIF{e_1}{\TRUE{}}{e_2}
|
|
|
\end{align*}
|
|
|
-By performing these translations in the front-end of the compiler,
|
|
|
+By performing these translations in the front end of the compiler,
|
|
|
subsequent passes of the compiler do not need to deal with these features,
|
|
|
-making the passes shorter.
|
|
|
+thus making the passes shorter.
|
|
|
|
|
|
-On the other hand, sometimes translations reduce the efficiency of the
|
|
|
+On the other hand, translations sometimes reduce the efficiency of the
|
|
|
generated code by increasing the number of instructions. For example,
|
|
|
expressing subtraction in terms of negation
|
|
|
\[
|
|
@@ -7794,7 +7794,7 @@ Add cases to \code{uniquify\_exp} to handle Boolean constants and
|
|
|
|
|
|
\begin{exercise}\normalfont\normalsize
|
|
|
Update the \code{uniquify\_exp} for \LangIf{} and add the following
|
|
|
-entry to the list of \code{passes} in the \code{run-tests.rkt} script.
|
|
|
+entry to the list of \code{passes} in the \code{run-tests.rkt} script:
|
|
|
\begin{lstlisting}
|
|
|
(list "uniquify" uniquify interp_Lif type_check_Lif)
|
|
|
\end{lstlisting}
|
|
@@ -7808,10 +7808,10 @@ Run the script to test your compiler.
|
|
|
|
|
|
The output language of \code{remove\_complex\_operands} is
|
|
|
\LangIfANF{} (figure~\ref{fig:Lif-anf-syntax}), the monadic
|
|
|
-normal form of \LangIf{}. A Boolean constant is an atomic expressions
|
|
|
-but the \code{if} expression is not. All three sub-expressions of an
|
|
|
-\code{if} are allowed to be complex expressions but the operands of
|
|
|
-\code{not} and the comparisons must be atomic.
|
|
|
+normal form of \LangIf{}. A Boolean constant is an atomic expression,
|
|
|
+but the \code{if} expression is not. All three subexpressions of an
|
|
|
+\code{if} are allowed to be complex expressions, but the operands of
|
|
|
+the \code{not} operator and comparison operators must be atomic.
|
|
|
%
|
|
|
\python{We add a new language form, the \code{Begin} expression, to aid
|
|
|
in the translation of \code{if} expressions. When we recursively
|
|
@@ -7826,12 +7826,12 @@ but the \code{if} expression is not. All three sub-expressions of an
|
|
|
expression $e$.}
|
|
|
|
|
|
Add cases to the \code{rco\_exp} and \code{rco\_atom} functions for
|
|
|
-the new features in \LangIf{}. When recursively processing
|
|
|
+the new features in \LangIf{}. In recursively processing
|
|
|
subexpressions, recall that you should invoke \code{rco\_atom} when
|
|
|
the output needs to be an \Atm{} (as specified in the grammar for
|
|
|
\LangIfANF{}) and invoke \code{rco\_exp} when the output should be
|
|
|
-\Exp{}. Regarding \code{if}, it is particularly important to
|
|
|
-\textbf{not} replace its condition with a temporary variable because
|
|
|
+\Exp{}. Regarding \code{if}, it is particularly important
|
|
|
+\textbf{not} to replace its condition with a temporary variable, because
|
|
|
that would interfere with the generation of high-quality output in the
|
|
|
upcoming \code{explicate\_control} pass.
|
|
|
|
|
@@ -7913,16 +7913,16 @@ list of \code{passes} and then run the script to test your compiler.
|
|
|
|
|
|
\racket{Recall that the purpose of \code{explicate\_control} is to
|
|
|
make the order of evaluation explicit in the syntax of the program.
|
|
|
- With the addition of \key{if} this gets more interesting.}
|
|
|
+ With the addition of \key{if}, this becomes more interesting.}
|
|
|
%
|
|
|
The \code{explicate\_control} pass translates from \LangIf{} to \LangCIf{}.
|
|
|
%
|
|
|
The main challenge to overcome is that the condition of an \key{if}
|
|
|
-can be an arbitrary expression in \LangIf{} whereas in \LangCIf{} the
|
|
|
+can be an arbitrary expression in \LangIf{}, whereas in \LangCIf{} the
|
|
|
condition must be a comparison.
|
|
|
|
|
|
As a motivating example, consider the following program that has an
|
|
|
-\key{if} expression nested in the condition of another \key{if}.%
|
|
|
+\key{if} expression nested in the condition of another \key{if}:%
|
|
|
\python{\footnote{Programmers rarely write nested \code{if}
|
|
|
expressions, but it is not uncommon for the condition of an
|
|
|
\code{if} statement to be a call of a function that also contains an
|
|
@@ -7957,8 +7957,8 @@ Each comparison would be translated into a \key{cmpq} instruction
|
|
|
followed by several instructions to move the result from the EFLAGS
|
|
|
register into a general purpose register or stack location. Each
|
|
|
\key{if} would be translated into a \key{cmpq} instruction followed by
|
|
|
-a conditional jump. The generated code for the inner \key{if} in the
|
|
|
-above example would be as follows.
|
|
|
+a conditional jump. The generated code for the inner \key{if} in this
|
|
|
+example would be as follows:
|
|
|
\begin{center}
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
\begin{lstlisting}
|
|
@@ -7975,10 +7975,10 @@ Notice that the three instructions starting with \code{setl} are
|
|
|
redundant: the conditional jump could come immediately after the first
|
|
|
\code{cmpq}.
|
|
|
|
|
|
-Our goal will be to compile \key{if} expressions so that the relevant
|
|
|
+Our goal is to compile \key{if} expressions so that the relevant
|
|
|
comparison instruction appears directly before the conditional jump.
|
|
|
For example, we want to generate the following code for the inner
|
|
|
-\code{if}.
|
|
|
+\code{if}:
|
|
|
\begin{center}
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
\begin{lstlisting}
|
|
@@ -7990,7 +7990,7 @@ For example, we want to generate the following code for the inner
|
|
|
\end{center}
|
|
|
One way to achieve this goal is to reorganize the code at the level of
|
|
|
\LangIf{}, pushing the outer \key{if} inside the inner one, yielding
|
|
|
-the following code.
|
|
|
+the following code:
|
|
|
\begin{center}
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
{\if\edition\racketEd
|
|
@@ -8018,17 +8018,17 @@ print(((y + 2) if x == 0 else (y + 10)) \
|
|
|
\end{minipage}
|
|
|
\end{center}
|
|
|
Unfortunately, this approach duplicates the two branches from the
|
|
|
-outer \code{if} and a compiler must never duplicate code! After all,
|
|
|
+outer \code{if}, and a compiler must never duplicate code! After all,
|
|
|
the two branches could be very large expressions.
|
|
|
|
|
|
-How can we apply the above transformation but without duplicating
|
|
|
-code? In other words, how can two different parts of a program refer
|
|
|
-to one piece of code.
|
|
|
+How can we apply this transformation without duplicating code? In
|
|
|
+other words, how can two different parts of a program refer to one
|
|
|
+piece of code?
|
|
|
%
|
|
|
The answer is that we must move away from abstract syntax \emph{trees}
|
|
|
and instead use \emph{graphs}.
|
|
|
%
|
|
|
-At the level of x86 assembly this is straightforward because we can
|
|
|
+At the level of x86 assembly, this is straightforward because we can
|
|
|
label the code for each branch and insert jumps in all the places that
|
|
|
need to execute the branch. In this way, jump instructions are edges
|
|
|
in the graph and the basic blocks are the nodes.
|
|
@@ -8038,10 +8038,10 @@ sequence of statements and to jump to a label via \code{goto}.
|
|
|
|
|
|
As a preview of what \code{explicate\_control} will do,
|
|
|
figure~\ref{fig:explicate-control-s1-38} shows the output of
|
|
|
-\code{explicate\_control} on the above example. Note how the condition
|
|
|
-of every \code{if} is a comparison operation and that we have not
|
|
|
-duplicated any code, but instead used labels and \code{goto} to enable
|
|
|
-sharing of code.
|
|
|
+\code{explicate\_control} on this example. Note how the condition of
|
|
|
+every \code{if} is a comparison operation and that we have not
|
|
|
+duplicated any code but instead have used labels and \code{goto} to
|
|
|
+enable sharing of code.
|
|
|
|
|
|
\begin{figure}[tbp]
|
|
|
\begin{tcolorbox}[colback=white]
|
|
@@ -8158,16 +8158,16 @@ block_1:
|
|
|
Recall that in section~\ref{sec:explicate-control-Lvar} we implement
|
|
|
\code{explicate\_control} for \LangVar{} using two recursive
|
|
|
functions, \code{explicate\_tail} and \code{explicate\_assign}. The
|
|
|
-former function translates expressions in tail position whereas the
|
|
|
-later function translates expressions on the right-hand side of a
|
|
|
+former function translates expressions in tail position, whereas the
|
|
|
+latter function translates expressions on the right-hand side of a
|
|
|
\key{let}. With the addition of \key{if} expression to \LangIf{} we
|
|
|
have a new kind of position to deal with: the predicate position of
|
|
|
the \key{if}. We need another function, \code{explicate\_pred}, that
|
|
|
-decides how to compile an \key{if} by analyzing its condition. So
|
|
|
+decides how to compile an \key{if} by analyzing its condition. So,
|
|
|
\code{explicate\_pred} takes an \LangIf{} expression and two
|
|
|
-\LangCIf{} tails for the then-branch and else-branch and outputs a
|
|
|
-tail. In the following paragraphs we discuss specific cases in the
|
|
|
-\code{explicate\_tail}, \code{explicate\_assign}, and
|
|
|
+\LangCIf{} tails for the \emph{then} branch and \emph{else} branch
|
|
|
+and outputs a tail. In the following paragraphs we discuss specific
|
|
|
+cases in the \code{explicate\_tail}, \code{explicate\_assign}, and
|
|
|
\code{explicate\_pred} functions.
|
|
|
%
|
|
|
\fi}
|
|
@@ -8339,7 +8339,8 @@ compiled to \code{return (+ x 2);} and passed as the \code{cont}
|
|
|
parameter of \code{explicate\_assign}. We'll need to use \code{cont}
|
|
|
to recursively process both branches of the \code{if}, and we do not
|
|
|
want to duplicate code, so we generate the following block using an
|
|
|
-auxiliary function named \code{create\_block} that we discuss below.
|
|
|
+auxiliary function named \code{create\_block}, discussed in the next
|
|
|
+section.
|
|
|
\begin{lstlisting}
|
|
|
block_6:
|
|
|
return (+ x 2)
|
|
@@ -8362,7 +8363,7 @@ goto block_6;
|
|
|
\end{minipage}
|
|
|
\end{center}
|
|
|
Finally, we delegate to \code{explicate\_pred}, passing the condition
|
|
|
-\code{(eq? y 0)} and the above code for the branches.
|
|
|
+\code{(eq? y 0)} and the previously presented code for the branches.
|
|
|
|
|
|
\subsection{Create Block}
|
|
|
|
|
@@ -8417,10 +8418,10 @@ then there is no need to generate a new label and entry in
|
|
|
|
|
|
\racket{The skeleton for the \code{explicate\_pred} function is given
|
|
|
in figure~\ref{fig:explicate-pred}. It takes three parameters:
|
|
|
- 1) \code{cnd}, the condition expression of the \code{if},
|
|
|
- 2) \code{thn}, the code generated by explicate for the ``then'' branch,
|
|
|
- and 3) \code{els}, the code generated by
|
|
|
- explicate for the ``else'' branch. The \code{explicate\_pred}
|
|
|
+ (1) \code{cnd}, the condition expression of the \code{if};
|
|
|
+ (2) \code{thn}, the code generated by explicate for the \emph{then} branch;
|
|
|
+ and (3) \code{els}, the code generated by
|
|
|
+ explicate for the \emph{else} branch. The \code{explicate\_pred}
|
|
|
function should match on \code{cnd} with a case for
|
|
|
every kind of expression that can have type \BOOLTY{}.}
|
|
|
%
|
|
@@ -8436,7 +8437,7 @@ comparison to an \code{if} statement whose branches are \code{goto}
|
|
|
statements created by applying \code{create\_block} to the code
|
|
|
generated for the \code{thn} and \code{els} branches. Let us
|
|
|
illustrate this translation by returning to the program with an
|
|
|
-\code{if} expression in tail position, shown again below. We invoke
|
|
|
+\code{if} expression in tail position, shown next. We invoke
|
|
|
\code{explicate\_pred} on its condition \racket{\code{(eq? x 0)}}
|
|
|
\python{\code{x == 0}}.
|
|
|
%
|
|
@@ -8456,7 +8457,7 @@ x = input_int()
|
|
|
%
|
|
|
\noindent The two branches \code{42} and \code{777} were already
|
|
|
compiled to \code{return} statements, from which we now create the
|
|
|
-following blocks.
|
|
|
+following blocks:
|
|
|
%
|
|
|
\begin{center}
|
|
|
\begin{minipage}{\textwidth}
|
|
@@ -8472,7 +8473,7 @@ block_2:
|
|
|
After that, \code{explicate\_pred} compiles the comparison
|
|
|
\racket{\code{(eq? x 0)}}
|
|
|
\python{\code{x == 0}}
|
|
|
-to the following \code{if} statement.
|
|
|
+to the following \code{if} statement:
|
|
|
%
|
|
|
{\if\edition\racketEd
|
|
|
\begin{center}
|
|
@@ -8500,9 +8501,9 @@ else
|
|
|
\fi}
|
|
|
Next consider the case for Boolean constants. We perform a kind of
|
|
|
partial evaluation\index{subject}{partial evaluation} and output
|
|
|
-either the \code{thn} or \code{els} branch depending on whether the
|
|
|
+either the \code{thn} or \code{els} branch, depending on whether the
|
|
|
constant is \TRUE{} or \FALSE{}. Let us illustrate this with the
|
|
|
-following program.
|
|
|
+following program:
|
|
|
{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
(if #t 42 777)
|
|
@@ -8517,7 +8518,7 @@ following program.
|
|
|
\noindent Again, the two branches \code{42} and \code{777} were
|
|
|
compiled to \code{return} statements, so \code{explicate\_pred}
|
|
|
compiles the constant \racket{\code{\#t}} \python{\code{True}} to the
|
|
|
-code for the ``then'' branch.
|
|
|
+code for the \emph{then} branch.
|
|
|
\begin{lstlisting}
|
|
|
return 42;
|
|
|
\end{lstlisting}
|
|
@@ -8525,21 +8526,22 @@ This case demonstrates that we sometimes discard the \code{thn} or
|
|
|
\code{els} blocks that are input to \code{explicate\_pred}.
|
|
|
|
|
|
The case for \key{if} expressions in \code{explicate\_pred} is
|
|
|
-particularly illuminating because it deals with the challenges we
|
|
|
-discussed above regarding nested \key{if} expressions
|
|
|
+particularly illuminating because it deals with the challenges
|
|
|
+discussed previously regarding nested \key{if} expressions
|
|
|
(figure~\ref{fig:explicate-control-s1-38}). The
|
|
|
\racket{\lstinline{thn^}}\python{\code{body}} and
|
|
|
\racket{\lstinline{els^}}\python{\code{orelse}} branches of the
|
|
|
\key{if} inherit their context from the current one, that is,
|
|
|
-predicate context. So you should recursively apply
|
|
|
+predicate context. So, you should recursively apply
|
|
|
\code{explicate\_pred} to the
|
|
|
\racket{\lstinline{thn^}}\python{\code{body}} and
|
|
|
\racket{\lstinline{els^}}\python{\code{orelse}} branches. For both of
|
|
|
those recursive calls, pass \code{thn} and \code{els} as the extra
|
|
|
-parameters. Thus, \code{thn} and \code{els} may get used twice, once
|
|
|
-inside each recursive call. As discussed above, to avoid duplicating
|
|
|
-code, we need to add them to the dictionary of basic blocks so that we
|
|
|
-can instead refer to them by name and execute them with a \key{goto}.
|
|
|
+parameters. Thus, \code{thn} and \code{els} may be used twice, once
|
|
|
+inside each recursive call. As discussed previously, to avoid
|
|
|
+duplicating code, we need to add them to the dictionary of basic
|
|
|
+blocks so that we can instead refer to them by name and execute them
|
|
|
+with a \key{goto}.
|
|
|
|
|
|
{\if\edition\pythonEd
|
|
|
%
|
|
@@ -8634,7 +8636,7 @@ Following the order of evaluation in the output of
|
|
|
and then the comparison \racket{\code{(< x 1)}}\python{\code{x < 1}}
|
|
|
in the predicate of the inner \key{if}. In the output of
|
|
|
\code{explicate\_control}, in the
|
|
|
-block labeled \code{start}, are two assignment statements followed by a
|
|
|
+block labeled \code{start}, two assignment statements are followed by an
|
|
|
\code{if} statement that branches to \code{block\_4} or
|
|
|
\code{block\_5}. The blocks associated with those labels contain the
|
|
|
translations of the code
|
|
@@ -8645,7 +8647,7 @@ respectively. In particular, we start \code{block\_4} with the
|
|
|
comparison
|
|
|
\racket{\code{(eq? x 0)}}\python{\code{x == 0}}
|
|
|
and then branch to \code{block\_2} or \code{block\_3},
|
|
|
-which correspond to the two branches of the outer \key{if}, i.e.,
|
|
|
+which correspond to the two branches of the outer \key{if}, that is,
|
|
|
\racket{\code{(+ y 2)}}\python{\code{y + 2}} and
|
|
|
\racket{\code{(+ y 10)}}\python{\code{y + 10}}.
|
|
|
%
|
|
@@ -8662,7 +8664,7 @@ The story for \code{block\_5} is similar to that of \code{block\_4}.
|
|
|
The way in which the \code{shrink} pass transforms logical operations
|
|
|
such as \code{and} and \code{or} can impact the quality of code
|
|
|
generated by \code{explicate\_control}. For example, consider the
|
|
|
-following program.
|
|
|
+following program:
|
|
|
% cond_test_21.rkt, and_eq_input.py
|
|
|
\begin{lstlisting}
|
|
|
(if (and (eq? (read) 0) (eq? (read) 1))
|
|
@@ -8670,11 +8672,12 @@ following program.
|
|
|
42)
|
|
|
\end{lstlisting}
|
|
|
The \code{and} operation should transform into something that the
|
|
|
-\code{explicate\_pred} function can still analyze and descend through to
|
|
|
-reach the underlying \code{eq?} conditions. Ideally, your
|
|
|
-\code{explicate\_control} pass should generate code similar to the
|
|
|
-following for the above program.
|
|
|
+\code{explicate\_pred} function can analyze and descend through to
|
|
|
+reach the underlying \code{eq?} conditions. Ideally, for this program
|
|
|
+your \code{explicate\_control} pass should generate code similar to
|
|
|
+the following:
|
|
|
\begin{center}
|
|
|
+\begin{minipage}{\textwidth}
|
|
|
\begin{lstlisting}
|
|
|
start:
|
|
|
tmp1 = (read);
|
|
@@ -8689,6 +8692,7 @@ block38:
|
|
|
block39:
|
|
|
return 42;
|
|
|
\end{lstlisting}
|
|
|
+\end{minipage}
|
|
|
\end{center}
|
|
|
\fi}
|
|
|
|
|
@@ -8701,20 +8705,20 @@ Boolean constants and \key{if} to the \code{explicate\_tail} and
|
|
|
\python{Implement \code{explicate\_control} pass with its
|
|
|
four auxiliary functions.}
|
|
|
%
|
|
|
-Create test cases that exercise all of the new cases in the code for
|
|
|
+Create test cases that exercise all the new cases in the code for
|
|
|
this pass.
|
|
|
%
|
|
|
{\if\edition\racketEd
|
|
|
Add the following entry to the list of \code{passes} in
|
|
|
-\code{run-tests.rkt} and then run this script to test your compiler.
|
|
|
+\code{run-tests.rkt}:
|
|
|
\begin{lstlisting}
|
|
|
(list "explicate_control" explicate_control interp-Cif type-check-Cif)
|
|
|
\end{lstlisting}
|
|
|
+and then run \code{run-tests.rkt} to test your compiler.
|
|
|
\fi}
|
|
|
|
|
|
\end{exercise}
|
|
|
|
|
|
-\clearpage
|
|
|
|
|
|
\section{Select Instructions}
|
|
|
\label{sec:select-Lif}
|
|
@@ -8738,9 +8742,9 @@ We take the usual approach of encoding them as integers.
|
|
|
\]
|
|
|
|
|
|
For translating statements, we discuss some of the cases. The
|
|
|
-\code{not} operation can be implemented in terms of \code{xorq} as we
|
|
|
+\code{not} operation can be implemented in terms of \code{xorq}, as we
|
|
|
discussed at the beginning of this section. Given an assignment, if
|
|
|
-the left-hand side variable is the same as the argument of \code{not},
|
|
|
+the left-hand-side variable is the same as the argument of \code{not},
|
|
|
then just the \code{xorq} instruction suffices.
|
|
|
\[
|
|
|
\CASSIGN{\Var}{ \CUNIOP{\key{not}}{\Var} }
|
|
@@ -8779,8 +8783,8 @@ movzbq %al, |$\Var$|
|
|
|
\end{lstlisting}
|
|
|
\end{minipage}
|
|
|
\end{tabular} \\
|
|
|
-The translations for the other comparison operators are similar to the
|
|
|
-above but use different condition codes for the \code{set} instruction.
|
|
|
+The translations for the other comparison operators are similar to
|
|
|
+this but use different condition codes for the \code{set} instruction.
|
|
|
|
|
|
\racket{Regarding the $\Tail$ nonterminal, we have two new cases:
|
|
|
\key{goto} and \key{if} statements. Both are straightforward to
|
|
@@ -8792,8 +8796,8 @@ A \key{goto} statement becomes a jump instruction.
|
|
|
\]
|
|
|
%
|
|
|
An \key{if} statement becomes a compare instruction followed by a
|
|
|
-conditional jump (for the ``then'' branch) and the fall-through is to
|
|
|
-a regular jump (for the ``else'' branch).\\
|
|
|
+conditional jump (for the \emph{then} branch), and the fall-through is to
|
|
|
+a regular jump (for the \emph{else} branch).\\
|
|
|
\begin{tabular}{lll}
|
|
|
\begin{minipage}{0.4\textwidth}
|
|
|
\begin{lstlisting}
|
|
@@ -8814,8 +8818,8 @@ jmp |$\ell_2$|
|
|
|
\end{lstlisting}
|
|
|
\end{minipage}
|
|
|
\end{tabular} \\
|
|
|
-Again, the translations for the other comparison operators are similar to the
|
|
|
-above but use different condition codes for the conditional jump instruction.
|
|
|
+Again, the translations for the other comparison operators are similar to this
|
|
|
+but use different condition codes for the conditional jump instruction.
|
|
|
|
|
|
\python{Regarding the \key{return} statement, we recommend treating it
|
|
|
as an assignment to the \key{rax} register followed by a jump to the
|
|
@@ -8857,10 +8861,10 @@ the addition of \key{if} expressions to \LangIf{},
|
|
|
%% \code{uncover\_live\_CFG} that applies liveness analysis to a
|
|
|
%% control-flow graph.
|
|
|
|
|
|
-The first question is: in what order should we process the basic blocks?
|
|
|
+The first question is, in what order should we process the basic blocks?
|
|
|
Recall that to perform liveness analysis on a basic block we need to
|
|
|
know the live-after set for the last instruction in the block. If a
|
|
|
-basic block has no successors (i.e. contains no jumps to other
|
|
|
+basic block has no successors (i.e., contains no jumps to other
|
|
|
blocks), then it has an empty live-after set and we can immediately
|
|
|
apply liveness analysis to it. If a basic block has some successors,
|
|
|
then we need to complete liveness analysis on those blocks
|
|
@@ -8886,10 +8890,10 @@ control-flow graphs that we generate from \LangIf{} programs.
|
|
|
However, in chapter~\ref{ch:Lwhile} we add loops to create \LangLoop{}
|
|
|
and learn how to handle cycles in the control-flow graph.
|
|
|
|
|
|
-\racket{You'll need to construct a directed graph to represent the
|
|
|
+\racket{You need to construct a directed graph to represent the
|
|
|
control-flow graph. Do not use the \code{directed-graph} of the
|
|
|
- \code{graph} package because that only allows at most one edge
|
|
|
- between each pair of vertices, but a control-flow graph may have
|
|
|
+ \code{graph} package because that allows at most one edge
|
|
|
+ between each pair of vertices, whereas a control-flow graph may have
|
|
|
multiple edges between a pair of vertices. The \code{multigraph.rkt}
|
|
|
file in the support code implements a graph representation that
|
|
|
allows multiple edges between a pair of vertices.}
|
|
@@ -8922,8 +8926,8 @@ block's label in the \code{live\_before\_block} dictionary.
|
|
|
|
|
|
In \LangXIfVar{} we also have the conditional jump
|
|
|
$\JMPIF{\itm{cc}}{\itm{label}}$ to deal with. Liveness analysis for
|
|
|
-this instruction is particularly interesting because, during
|
|
|
-compilation, we do not know which way a conditional jump will go. So
|
|
|
+this instruction is particularly interesting because during
|
|
|
+compilation, we do not know which way a conditional jump will go. Thus
|
|
|
we do not know whether to use the live-before set for the block
|
|
|
associated with the $\itm{label}$ or the live-before set for the
|
|
|
following instruction. However, there is no harm to the correctness
|
|
@@ -8945,7 +8949,7 @@ Update the \code{uncover\_live} pass to apply liveness analysis to
|
|
|
every basic block in the program.
|
|
|
%
|
|
|
Add the following entry to the list of \code{passes} in the
|
|
|
-\code{run-tests.rkt} script.
|
|
|
+\code{run-tests.rkt} script:
|
|
|
\begin{lstlisting}
|
|
|
(list "uncover_live" uncover_live interp-pseudo-x86-1)
|
|
|
\end{lstlisting}
|
|
@@ -8974,15 +8978,15 @@ same way as the instructions in \LangXVar{}.
|
|
|
% out the computing of the the read and write sets for each kind of
|
|
|
% instruction into auxiliary functions.
|
|
|
%
|
|
|
-Some instructions, e.g., the \key{movzbq} instruction, require special care,
|
|
|
-similar to the \key{movq} instruction. See rule number 1 in
|
|
|
+Some instructions, such as the \key{movzbq} instruction, require special care,
|
|
|
+similar to the \key{movq} instruction. Refer to rule number 1 in
|
|
|
section~\ref{sec:build-interference}.
|
|
|
|
|
|
\begin{exercise}\normalfont\normalsize
|
|
|
Update the \code{build\_interference} pass for \LangXIfVar{}.
|
|
|
{\if\edition\racketEd
|
|
|
Add the following entries to the list of \code{passes} in the
|
|
|
-\code{run-tests.rkt} script.
|
|
|
+\code{run-tests.rkt} script:
|
|
|
\begin{lstlisting}
|
|
|
(list "build_interference" build_interference interp-pseudo-x86-1)
|
|
|
(list "allocate_registers" allocate_registers interp-pseudo-x86-1)
|
|
@@ -9000,7 +9004,7 @@ restrictions that need to be handled in the \code{patch\_instructions}
|
|
|
pass.
|
|
|
%
|
|
|
The second argument of the \key{cmpq} instruction must not be an
|
|
|
-immediate value (such as an integer). So if you are comparing two
|
|
|
+immediate value (such as an integer). So, if you are comparing two
|
|
|
immediates, we recommend inserting a \key{movq} instruction to put the
|
|
|
second argument in \key{rax}. As usual, \key{cmpq} may have at most
|
|
|
one memory reference.
|
|
@@ -9013,7 +9017,7 @@ Update \code{patch\_instructions} pass for \LangXIfVar{}.
|
|
|
%
|
|
|
{\if\edition\racketEd
|
|
|
Add the following entry to the list of \code{passes} in
|
|
|
-\code{run-tests.rkt} and then run this script to test your compiler.
|
|
|
+\code{run-tests.rkt}, and then run this script to test your compiler.
|
|
|
\begin{lstlisting}
|
|
|
(list "patch_instructions" patch_instructions interp-x86-1)
|
|
|
\end{lstlisting}
|
|
@@ -9211,32 +9215,32 @@ conclusion:
|
|
|
\begin{figure}[tbp]
|
|
|
\begin{tcolorbox}[colback=white]
|
|
|
{\if\edition\racketEd
|
|
|
-\begin{tikzpicture}[baseline=(current bounding box.center)]
|
|
|
+\begin{tikzpicture}[baseline=(current bounding box.center),scale=0.90]
|
|
|
\node (Lif) at (0,2) {\large \LangIf{}};
|
|
|
\node (Lif-2) at (3,2) {\large \LangIf{}};
|
|
|
\node (Lif-3) at (6,2) {\large \LangIf{}};
|
|
|
\node (Lif-4) at (9,2) {\large \LangIf{}};
|
|
|
\node (Lif-5) at (9,0) {\large \LangIfANF{}};
|
|
|
-\node (C1-1) at (3,0) {\large \LangCIf{}};
|
|
|
+\node (C1-1) at (0,0) {\large \LangCIf{}};
|
|
|
|
|
|
-\node (x86-2) at (3,-2) {\large \LangXIfVar{}};
|
|
|
-\node (x86-2-1) at (3,-4) {\large \LangXIfVar{}};
|
|
|
-\node (x86-2-2) at (6,-4) {\large \LangXIfVar{}};
|
|
|
-\node (x86-3) at (6,-2) {\large \LangXIfVar{}};
|
|
|
-\node (x86-4) at (9,-2) {\large \LangXIf{}};
|
|
|
-\node (x86-5) at (9,-4) {\large \LangXIf{}};
|
|
|
+\node (x86-2) at (0,-2) {\large \LangXIfVar{}};
|
|
|
+\node (x86-2-1) at (0,-4) {\large \LangXIfVar{}};
|
|
|
+\node (x86-2-2) at (4,-4) {\large \LangXIfVar{}};
|
|
|
+\node (x86-3) at (4,-2) {\large \LangXIfVar{}};
|
|
|
+\node (x86-4) at (8,-2) {\large \LangXIf{}};
|
|
|
+\node (x86-5) at (8,-4) {\large \LangXIf{}};
|
|
|
|
|
|
\path[->,bend left=15] (Lif) edge [above] node {\ttfamily\footnotesize type\_check} (Lif-2);
|
|
|
\path[->,bend left=15] (Lif-2) edge [above] node {\ttfamily\footnotesize shrink} (Lif-3);
|
|
|
\path[->,bend left=15] (Lif-3) edge [above] node {\ttfamily\footnotesize uniquify} (Lif-4);
|
|
|
-\path[->,bend left=15] (Lif-4) edge [right] node {\ttfamily\footnotesize remove\_complex.} (Lif-5);
|
|
|
-\path[->,bend right=15] (Lif-5) edge [above] node {\ttfamily\footnotesize explicate\_control} (C1-1);
|
|
|
-\path[->,bend right=15] (C1-1) edge [left] node {\ttfamily\footnotesize select\_instr.} (x86-2);
|
|
|
+\path[->,bend left=15] (Lif-4) edge [left] node {\ttfamily\footnotesize remove\_complex\_operands} (Lif-5);
|
|
|
+\path[->,bend left=10] (Lif-5) edge [above] node {\ttfamily\footnotesize explicate\_control} (C1-1);
|
|
|
+\path[->,bend right=15] (C1-1) edge [right] node {\ttfamily\footnotesize select\_instructions} (x86-2);
|
|
|
\path[->,bend left=15] (x86-2) edge [right] node {\ttfamily\footnotesize uncover\_live} (x86-2-1);
|
|
|
-\path[->,bend right=15] (x86-2-1) edge [below] node {\ttfamily\footnotesize build\_inter.} (x86-2-2);
|
|
|
-\path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize allocate\_reg.} (x86-3);
|
|
|
-\path[->,bend left=15] (x86-3) edge [above] node {\ttfamily\footnotesize patch\_instr.} (x86-4);
|
|
|
-\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize print\_x86 } (x86-5);
|
|
|
+\path[->,bend right=15] (x86-2-1) edge [below] node {\ttfamily\footnotesize build\_interference} (x86-2-2);
|
|
|
+\path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize allocate\_registers} (x86-3);
|
|
|
+\path[->,bend left=15] (x86-3) edge [above] node {\ttfamily\footnotesize patch\_instructions} (x86-4);
|
|
|
+\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize prelude\_and\_conclusion } (x86-5);
|
|
|
\end{tikzpicture}
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
@@ -9284,7 +9288,7 @@ blocks. It creates a basic block whenever a continuation \emph{might}
|
|
|
get used more than once (e.g., whenever the \code{cont} parameter is
|
|
|
passed into two or more recursive calls). However, some continuation
|
|
|
arguments may not be used at all. For example, consider the case for
|
|
|
-the constant \TRUE{} in \code{explicate\_pred}, where we discard the
|
|
|
+the constant \TRUE{} in \code{explicate\_pred}, in which we discard the
|
|
|
\code{els} continuation.
|
|
|
%
|
|
|
{\if\edition\racketEd
|
|
@@ -9327,11 +9331,11 @@ block_7:
|
|
|
\end{center}
|
|
|
\fi}
|
|
|
|
|
|
-So the question is how can we decide whether to create a basic block?
|
|
|
+The question is, how can we decide whether to create a basic block?
|
|
|
\emph{Lazy evaluation}\index{subject}{lazy
|
|
|
evaluation}~\citep{Friedman:1976aa} can solve this conundrum by
|
|
|
-delaying the creation of a basic block until the point in time where
|
|
|
-we know it will be used.
|
|
|
+delaying the creation of a basic block until the point in time at which
|
|
|
+we know that it will be used.
|
|
|
%
|
|
|
{\if\edition\racketEd
|
|
|
%
|
|
@@ -9379,24 +9383,24 @@ We use promises for the input and output of the functions
|
|
|
%
|
|
|
\racket{ and \code{explicate\_tail}}\python{ \code{explicate\_effect}, and \code{explicate\_stmt}}.
|
|
|
%
|
|
|
-So instead of taking and returning \racket{$\Tail$
|
|
|
+So, instead of taking and returning \racket{$\Tail$
|
|
|
expressions}\python{lists of statements}, they take and return
|
|
|
promises. Furthermore, when we come to a situation in which a
|
|
|
continuation might be used more than once, as in the case for
|
|
|
\code{if} in \code{explicate\_pred}, we create a delayed computation
|
|
|
that creates a basic block for each continuation (if there is not
|
|
|
already one) and then returns a \code{goto} statement to that basic
|
|
|
-block. When we come to a situation where we have a promise but need an
|
|
|
-actual piece of code, e.g. to create a larger piece of code with a
|
|
|
+block. When we come to a situation in which we have a promise but need an
|
|
|
+actual piece of code, for example, to create a larger piece of code with a
|
|
|
constructor such as \code{Seq}, then insert a call to \code{force}.
|
|
|
%
|
|
|
{\if\edition\racketEd
|
|
|
%
|
|
|
-Also we must modify the \code{create\_block} function to begin with
|
|
|
+Also, we must modify the \code{create\_block} function to begin with
|
|
|
\code{delay} to create a promise. When forced, this promise forces the
|
|
|
original promise. If that returns a \code{Goto} (because the block was
|
|
|
already added to \code{basic-blocks}), then we return the
|
|
|
-\code{Goto}. Otherwise we add the block to \code{basic-blocks} and
|
|
|
+\code{Goto}. Otherwise, we add the block to \code{basic-blocks} and
|
|
|
return a \code{Goto} to the new label.
|
|
|
\begin{center}
|
|
|
\begin{minipage}{\textwidth}
|
|
@@ -9436,9 +9440,9 @@ def create_block(promise, basic_blocks):
|
|
|
\fi}
|
|
|
|
|
|
Figure~\ref{fig:explicate-control-challenge} shows the output of
|
|
|
-improved \code{explicate\_control} on the above example. As you can
|
|
|
-see, the number of basic blocks has been reduced from 4 blocks (see
|
|
|
-figure~\ref{fig:explicate-control-s1-38}) down to 2 blocks.
|
|
|
+improved \code{explicate\_control} on this example. As you can
|
|
|
+see, the number of basic blocks has been reduced from four blocks (see
|
|
|
+figure~\ref{fig:explicate-control-s1-38}) to two blocks.
|
|
|
|
|
|
\begin{figure}[tbp]
|
|
|
\begin{tcolorbox}[colback=white]
|
|
@@ -9638,7 +9642,7 @@ block_1:
|
|
|
\begin{exercise}\normalfont\normalsize
|
|
|
Implement the improvements to the \code{explicate\_control} pass.
|
|
|
Check that it removes trivial blocks in a few example programs. Then
|
|
|
- check that your compiler still passes all of your tests.
|
|
|
+ check that your compiler still passes all your tests.
|
|
|
\end{exercise}
|
|
|
|
|
|
|
|
@@ -9646,10 +9650,10 @@ block_1:
|
|
|
|
|
|
There is an opportunity for removing jumps that is apparent in the
|
|
|
example of figure~\ref{fig:if-example-x86}. The \code{start} block
|
|
|
-ends with a jump to \code{block\_5} and there are no other jumps to
|
|
|
+ends with a jump to \code{block\_5}, and there are no other jumps to
|
|
|
\code{block\_5} in the rest of the program. In this situation we can
|
|
|
avoid the runtime overhead of this jump by merging \code{block\_5}
|
|
|
-into the preceding block, in this case the \code{start} block.
|
|
|
+into the preceding block, which in this case is the \code{start} block.
|
|
|
Figure~\ref{fig:remove-jumps} shows the output of
|
|
|
\code{allocate\_registers} on the left and the result of this
|
|
|
optimization on the right.
|
|
@@ -9747,7 +9751,7 @@ block. The pass should translate from \LangXIfVar{} to \LangXIfVar{}.
|
|
|
{\if\edition\racketEd
|
|
|
In the \code{run-tests.rkt} script, add the following entry to the
|
|
|
list of \code{passes} between \code{allocate\_registers}
|
|
|
-and \code{patch\_instructions}.
|
|
|
+and \code{patch\_instructions}:
|
|
|
\begin{lstlisting}
|
|
|
(list "remove-jumps" remove-jumps interp-pseudo-x86-1)
|
|
|
\end{lstlisting}
|