|
@@ -1300,7 +1300,7 @@ Figure~\ref{fig:x86-0-concrete} defines the concrete syntax for the subset of
|
|
|
the x86 assembly language needed for this chapter, which we call x86$_0$.
|
|
|
%
|
|
|
An x86 program begins with a \code{main} label followed by a sequence
|
|
|
-of instructions. In the grammar, elipses such as $\ldots$ are used to
|
|
|
+of instructions. In the grammar, ellipses such as $\ldots$ are used to
|
|
|
indicate a sequence of items, e.g., $\Instr \ldots$ is a sequence of
|
|
|
instructions.\index{instruction}
|
|
|
%
|
|
@@ -1444,7 +1444,7 @@ the top of the stack. The stack grows downward in memory, so we
|
|
|
increase the size of the stack by subtracting from the stack pointer.
|
|
|
In the context of a procedure call, the \emph{return
|
|
|
address}\index{return address} is the instruction after the call
|
|
|
-instruction on the caller side. The function call inststruction,
|
|
|
+instruction on the caller side. The function call instruction,
|
|
|
\code{callq}, pushes the return address onto the stack. The register
|
|
|
\key{rbp} is the \emph{base pointer}\index{base pointer} and is used
|
|
|
to access variables associated with the current procedure call. The
|
|
@@ -1495,7 +1495,7 @@ Position & Contents \\ \hline
|
|
|
\end{figure}
|
|
|
|
|
|
Getting back to the program in Figure~\ref{fig:p1-x86}, consider how
|
|
|
-control is transfered from the operating system to the \code{main}
|
|
|
+control is transferred from the operating system to the \code{main}
|
|
|
function. The operating system issues a \code{callq main} instruction
|
|
|
which pushes its return address on the stack and then jumps to
|
|
|
\code{main}. In x86-64, the stack pointer \code{rsp} must be divisible
|
|
@@ -2620,7 +2620,7 @@ approach is to assign a variable to one or more locations in different
|
|
|
regions of the program. For example, if a variable is used many times
|
|
|
in short sequence and then only used again after many other
|
|
|
instructions, it could be more efficient to assign the variable to a
|
|
|
-register during the intial sequence and then move it to the stack for
|
|
|
+register during the initial sequence and then move it to the stack for
|
|
|
the rest of its lifetime. We refer the interested reader to
|
|
|
\citet{Cooper:1998ly} and \citet{Cooper:2011aa} for more information
|
|
|
about that approach.
|
|
@@ -2705,7 +2705,7 @@ accidentally wiped out by the call to \code{read}. One obvious
|
|
|
approach is to save all the values in caller-saved registers to the
|
|
|
stack prior to each function call, and restore them after each
|
|
|
call. That way, if the register allocator chooses to assign \code{x}
|
|
|
-to a caller-saved register, its value will be preserved accross the
|
|
|
+to a caller-saved register, its value will be preserved across the
|
|
|
call to \code{read}. However, the disadvantage of this approach is
|
|
|
that saving and restoring to the stack is relatively slow. If \code{x}
|
|
|
is not used many times, it may be better to assign \code{x} to a stack
|
|
@@ -3386,7 +3386,7 @@ and \ttm{rsp} because they interfere with $\ttm{t}$.
|
|
|
\]
|
|
|
We repeat the process, selecting another maximally saturated
|
|
|
vertex, which is \code{z}, and color it with the first available
|
|
|
-number, which is $1$. We add $1$ to the saturations for the
|
|
|
+number, which is $1$. We add $1$ to the saturation for the
|
|
|
neighboring vertices \code{t}, \code{y}, \code{w}, and \code{rsp}.
|
|
|
\[
|
|
|
\begin{tikzpicture}[baseline=(current bounding box.center)]
|
|
@@ -3638,7 +3638,7 @@ notify the priority queue when their saturation changes.
|
|
|
\item[$\LP\code{pqueue-pop!}\,\itm{queue}\RP$] returns the item with
|
|
|
the lowest priority.
|
|
|
\item[$\LP\code{pqueue-decrease-key!}\,\itm{queue}\,\itm{handle}\RP$]
|
|
|
- notifices the queue the the priority has decreased for the item
|
|
|
+ notifies the queue that the priority has decreased for the item
|
|
|
associated with the given handle.
|
|
|
\end{description}
|
|
|
\end{tcolorbox}
|
|
@@ -4019,7 +4019,7 @@ stack, we have limited the register allocator to use just two
|
|
|
registers: \code{rbx} and \code{rcx}. In the prelude of the
|
|
|
\code{main} function, we push \code{rbx} onto the stack because it is
|
|
|
a callee-saved register and it was assigned to variable by the
|
|
|
-register allocator. We substract \code{8} from the \code{rsp} at the
|
|
|
+register allocator. We subtract \code{8} from the \code{rsp} at the
|
|
|
end of the prelude to reserve space for the one spilled variable.
|
|
|
After that subtraction, the \code{rsp} is aligned to 16 bytes.
|
|
|
|
|
@@ -4374,7 +4374,7 @@ variable \code{x}, it can find its type in the environment.
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
-Figure~\ref{fig:type-check-aux-R2} defines three auxilliary functions
|
|
|
+Figure~\ref{fig:type-check-aux-R2} defines three auxiliary functions
|
|
|
that are used in the type checker. The \code{operator-types} function
|
|
|
defines a dictionary that maps the operator names to their parameter
|
|
|
and return types. The \code{type-equal?} function determines whether
|
|
@@ -4414,7 +4414,7 @@ result is the return type of the operator.
|
|
|
[else
|
|
|
(error 'type-check-op "unrecognized operator ~a" op)]))
|
|
|
\end{lstlisting}
|
|
|
-\caption{Auxilliary functions for type checking.}
|
|
|
+\caption{Auxiliary functions for type checking.}
|
|
|
\label{fig:type-check-aux-R2}
|
|
|
\end{figure}
|
|
|
|
|
@@ -4671,7 +4671,7 @@ C_1 & ::= & \gray{\PROGRAM{\itm{info}}{\CFG{\key{(}\itm{label}\,\key{.}\,\Tail\k
|
|
|
\]
|
|
|
\end{minipage}
|
|
|
}
|
|
|
-\caption{The abstract syntax of $C_1$, an extention of $C_0$
|
|
|
+\caption{The abstract syntax of $C_1$, an extension of $C_0$
|
|
|
(Figure~\ref{fig:c0-syntax}).}
|
|
|
\label{fig:c1-syntax}
|
|
|
\end{figure}
|
|
@@ -5071,7 +5071,7 @@ following program.
|
|
|
42)
|
|
|
\end{lstlisting}
|
|
|
The \code{and} operation should transform into something that the
|
|
|
-\code{explicat-pred} function can still analyze and descend through to
|
|
|
+\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.
|
|
@@ -5222,20 +5222,22 @@ algorithm itself does not change.
|
|
|
Recall that for $R_1$ we implemented liveness analysis for a single
|
|
|
basic block (Section~\ref{sec:liveness-analysis-r1}). With the
|
|
|
addition of \key{if} expressions to $R_2$, \code{explicate-control}
|
|
|
-produces many basic blocks arranged in a control-flow graph. The first
|
|
|
-question we need to consider is: what order should we process the
|
|
|
-basic blocks? To perform liveness analysis on a basic block, we need
|
|
|
-to know its live-after set. If a basic block has no successor blocks
|
|
|
-(i.e. no out-edges in the control flow graph), 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 first. Thankfully, the control flow
|
|
|
-graph does not contain any cycles because $R_2$ does not include loops
|
|
|
-%
|
|
|
-\footnote{If we were to add loops to the language, then the CFG could
|
|
|
- contain cycles and we would need to use an iterative worklist
|
|
|
- algorithm for computing the fixed point of the liveness
|
|
|
- analysis~\citep{Aho:1986qf}.}.
|
|
|
+produces many basic blocks arranged in a control-flow graph. We
|
|
|
+recommend that you create a new auxiliary function named
|
|
|
+\code{uncover-live-CFG} that applies liveness analysis to a
|
|
|
+control-flow graph.
|
|
|
+
|
|
|
+The first question we need to consider is: what order should we
|
|
|
+process the basic blocks in the control-flow graph? To perform
|
|
|
+liveness analysis on a basic block, we need to know its live-after
|
|
|
+set. If a basic block has no successor blocks (i.e. no out-edges in
|
|
|
+the control flow graph), 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 first. Thankfully, the control flow graph does not contain any
|
|
|
+cycles because $R_2$ does not include loops. (In
|
|
|
+Chapter~\ref{ch:loop} we add loops and study how to handle cycles in
|
|
|
+the control-flow graph.)
|
|
|
%
|
|
|
Returning to the question of what order should we process the basic
|
|
|
blocks, the answer is reverse topological order. We recommend using
|
|
@@ -5571,7 +5573,7 @@ example of Figure~\ref{fig:if-example-x86}. The \code{start} block end
|
|
|
with a jump to \code{block7953} and there are no other jumps to
|
|
|
\code{block7953} in the rest of the program. In this situation we can
|
|
|
avoid the runtime overhead of this jump by merging \code{block7953}
|
|
|
-into the preceeding block, in this case the \code{start} block.
|
|
|
+into the preceding block, in this case the \code{start} block.
|
|
|
Figure~\ref{fig:remove-jumps} shows the output of
|
|
|
\code{select-instructions} on the left and the result of this
|
|
|
optimization on the right.
|
|
@@ -5618,8 +5620,8 @@ block7952:
|
|
|
|
|
|
\begin{exercise}\normalfont
|
|
|
Implement a pass named \code{remove-jumps} that merges basic blocks
|
|
|
- into their preceeding basic block, when there is only one preceeding
|
|
|
- block. The pass should translate from psuedo $x86_1$ to pseudo
|
|
|
+ into their preceding basic block, when there is only one preceding
|
|
|
+ block. The pass should translate from pseudo $x86_1$ to pseudo
|
|
|
$x86_1$ and it should come immediately after
|
|
|
\code{select-instructions}. Check that \code{remove-jumps}
|
|
|
accomplishes the goal of merging basic blocks on several test
|
|
@@ -5905,7 +5907,7 @@ start and end parentheses. \index{unquote-slicing}
|
|
|
[`(Vector ,ts ...)
|
|
|
(values (Prim 'vector-length (list e^)) 'Integer)]
|
|
|
[else (error 'type-check-exp
|
|
|
- "expected a vector in vector-lenfth, not ~a" t)])]
|
|
|
+ "expected a vector in vector-length, not ~a" t)])]
|
|
|
[(Prim 'eq? (list arg1 arg2))
|
|
|
(define-values (e1 t1) (recur arg1))
|
|
|
(define-values (e2 t2) (recur arg2))
|
|
@@ -6230,7 +6232,7 @@ compiler passes. We introduce a new compiler pass named
|
|
|
\code{expose-allocation}. We make
|
|
|
significant changes to \code{select-instructions},
|
|
|
\code{build-interference}, \code{allocate-registers}, and
|
|
|
-\code{print-x86} and make minor changes in severl more passes. The
|
|
|
+\code{print-x86} and make minor changes in several more passes. The
|
|
|
following program will serve as our running example. It creates two
|
|
|
tuples, one nested inside the other. Both tuples have length one. The
|
|
|
program accesses the element in the inner tuple tuple via two vector
|
|
@@ -6358,12 +6360,40 @@ Figure~\ref{fig:expose-alloc-output} shows the output of the
|
|
|
\label{sec:remove-complex-opera-R3}
|
|
|
|
|
|
The new forms \code{collect}, \code{allocate}, and \code{global-value}
|
|
|
-should all be treated as complex operands. A new case for
|
|
|
-\code{HasType} is needed and the case for \code{Prim} needs to be
|
|
|
-handled carefully to prevent the \code{Prim} node from being separated
|
|
|
-from its enclosing \code{HasType}.
|
|
|
+should all be treated as complex operands.
|
|
|
+%% A new case for
|
|
|
+%% \code{HasType} is needed and the case for \code{Prim} needs to be
|
|
|
+%% handled carefully to prevent the \code{Prim} node from being separated
|
|
|
+%% from its enclosing \code{HasType}.
|
|
|
+Figure~\ref{fig:r3-anf-syntax}
|
|
|
+shows the grammar for the output language $R_3^{\dagger}$ of this
|
|
|
+pass, which is $R_3$ in administrative normal form.
|
|
|
|
|
|
-TODO: add the grammar for the output language
|
|
|
+\begin{figure}[tp]
|
|
|
+\centering
|
|
|
+\fbox{
|
|
|
+\begin{minipage}{0.96\textwidth}
|
|
|
+\small
|
|
|
+\[
|
|
|
+\begin{array}{rcl}
|
|
|
+ \Atm &::=& \gray{ \INT{\Int} \mid \VAR{\Var} \mid \BOOL{\itm{bool}} }
|
|
|
+ \mid \VOID{} \\
|
|
|
+\Exp &::=& \gray{ \Atm \mid \READ{} } \\
|
|
|
+ &\mid& \gray{ \NEG{\Atm} \mid \ADD{\Atm}{\Atm} } \\
|
|
|
+ &\mid& \gray{ \LET{\Var}{\Exp}{\Exp} } \\
|
|
|
+ &\mid& \gray{ \UNIOP{\key{'not}}{\Atm} } \\
|
|
|
+ &\mid& \gray{ \BINOP{\itm{cmp}}{\Atm}{\Atm} \mid \IF{\Exp}{\Exp}{\Exp} }\\
|
|
|
+ &\mid& \LP\key{Collect}~\Int\RP \mid \LP\key{Allocate}~\Int~\Type\RP
|
|
|
+ \mid \LP\key{GlobalValue}~\Var\RP\\
|
|
|
+% &\mid& \LP\key{HasType}~\Exp~\Type\RP \\
|
|
|
+R^{\dagger}_3 &::=& \gray{ \PROGRAM{\code{'()}}{\Exp} }
|
|
|
+\end{array}
|
|
|
+\]
|
|
|
+\end{minipage}
|
|
|
+}
|
|
|
+\caption{$R_3^{\dagger}$ is $R_3$ in administrative normal form (ANF).}
|
|
|
+\label{fig:r3-anf-syntax}
|
|
|
+\end{figure}
|
|
|
|
|
|
|
|
|
\section{Explicate Control and the $C_2$ language}
|
|
@@ -6905,8 +6935,8 @@ instances.
|
|
|
\end{center}
|
|
|
Similarly, to write to a field of a structure, use its set function,
|
|
|
whose name starts with \code{set-}, followed by the structure name,
|
|
|
-then a dash, then the field name, and conclused with an exclamation
|
|
|
-mark. The folowing example uses \code{set-point-x!} to change the
|
|
|
+then a dash, then the field name, and concluded with an exclamation
|
|
|
+mark. The following example uses \code{set-point-x!} to change the
|
|
|
\code{x} field from \code{7} to \code{42}.
|
|
|
\begin{center}
|
|
|
\begin{lstlisting}
|
|
@@ -6934,7 +6964,7 @@ allocated data is more likely to become garbage then data that has
|
|
|
survived one or more previous calls to \code{collect}. This insight
|
|
|
motivated the creation of \emph{generational garbage collectors}
|
|
|
\index{generational garbage collector} that
|
|
|
-1) segragates data according to its age into two or more generations,
|
|
|
+1) segregates data according to its age into two or more generations,
|
|
|
2) allocates less space for younger generations, so collecting them is
|
|
|
faster, and more space for the older generations, and 3) performs
|
|
|
collection on the younger generations more frequently then for older
|
|
@@ -7520,22 +7550,7 @@ The concrete syntax for a function reference is $\CFUNREF{f}$.
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
\[
|
|
|
\begin{array}{lcl}
|
|
|
-\Exp &::=& \gray{ \INT{\Int} \mid \READ{} \mid \NEG{\Exp} } \\
|
|
|
- &\mid& \gray{ \ADD{\Exp}{\Exp}
|
|
|
- \mid \BINOP{\code{'-}}{\Exp}{\Exp} } \\
|
|
|
- &\mid& \gray{ \VAR{\Var} \mid \LET{\Var}{\Exp}{\Exp} } \\
|
|
|
- &\mid& \gray{ \BOOL{\itm{bool}}
|
|
|
- \mid \AND{\Exp}{\Exp} }\\
|
|
|
- &\mid& \gray{ \OR{\Exp}{\Exp}
|
|
|
- \mid \NOT{\Exp} } \\
|
|
|
- &\mid& \gray{ \BINOP{\itm{cmp}}{\Exp}{\Exp}
|
|
|
- \mid \IF{\Exp}{\Exp}{\Exp} } \\
|
|
|
- &\mid& \gray{ \VECTOR{\Exp} } \\
|
|
|
- &\mid& \gray{ \VECREF{\Exp}{\INT{\Int}} }\\
|
|
|
- &\mid& \gray{ \VECSET{\Exp}{\INT{\Int}}{\Exp}} \\
|
|
|
- &\mid& \gray{ \VOID{} \mid \LP\key{HasType}~\Exp~\Type \RP
|
|
|
- \mid \APPLY{\Exp}{\Exp\ldots} }\\
|
|
|
- &\mid& \FUNREF{\Var}\\
|
|
|
+\Exp &::=& \ldots \mid \FUNREF{\Var}\\
|
|
|
\Def &::=& \gray{ \FUNDEF{\Var}{([\Var \code{:} \Type]\ldots)}{\Type}{\code{'()}}{\Exp} }\\
|
|
|
F_1 &::=& \PROGRAMDEFS{\code{'()}}{\LP \Def\ldots \RP}
|
|
|
\end{array}
|
|
@@ -7580,7 +7595,7 @@ follows.
|
|
|
(Def |$f$| ([|$x_1$|:|$T_1$|] |$\ldots$| [|$x_5$|:|$T_5$|] [vec : (Vector |$T_6 \ldots T_n$|)]) |$T_r$| |$\itm{info}$| |$\itm{body}'$|)
|
|
|
\end{lstlisting}
|
|
|
where the $\itm{body}$ is transformed into $\itm{body}'$ by replacing
|
|
|
-the occurences of the later parameters with vector references.
|
|
|
+the occurrences of the later parameters with vector references.
|
|
|
\begin{lstlisting}
|
|
|
(Var |$x_i$|) |$\Rightarrow$| (Prim 'vector-ref (list vec (Int |$(i - 6)$|)))
|
|
|
\end{lstlisting}
|
|
@@ -7609,19 +7624,48 @@ $\Rightarrow$
|
|
|
\label{sec:rco-r4}
|
|
|
|
|
|
The primary decisions to make for this pass is whether to classify
|
|
|
-\code{FunRef} and \code{Apply} as either simple or complex
|
|
|
+\code{FunRef} and \code{Apply} as either atomic or complex
|
|
|
expressions. Recall that a simple expression will eventually end up as
|
|
|
-just an ``immediate'' argument of an x86 instruction. Function
|
|
|
+just an immediate argument of an x86 instruction. Function
|
|
|
application will be translated to a sequence of instructions, so
|
|
|
-\code{Apply} must be classified as complex expression. Regarding
|
|
|
-\code{FunRef}, as discussed above, the function label needs to
|
|
|
-be converted to an address using the \code{leaq} instruction. Thus,
|
|
|
+\code{Apply} must be classified as complex expression.
|
|
|
+On the other hand, the arguments of \code{Apply} should be
|
|
|
+atomic expressions.
|
|
|
+%
|
|
|
+Regarding \code{FunRef}, as discussed above, the function label needs
|
|
|
+to be converted to an address using the \code{leaq} instruction. Thus,
|
|
|
even though \code{FunRef} seems rather simple, it needs to be
|
|
|
classified as a complex expression so that we generate an assignment
|
|
|
statement with a left-hand side that can serve as the target of the
|
|
|
-\code{leaq}.
|
|
|
+\code{leaq}. Figure~\ref{fig:r4-anf-syntax} defines the
|
|
|
+output language $R_4^{\dagger}$ of this pass.
|
|
|
|
|
|
-TODO: add the output grammar
|
|
|
+\begin{figure}[tp]
|
|
|
+\centering
|
|
|
+\fbox{
|
|
|
+\begin{minipage}{0.96\textwidth}
|
|
|
+\small
|
|
|
+\[
|
|
|
+\begin{array}{rcl}
|
|
|
+ \Atm &::=& \gray{ \INT{\Int} \mid \VAR{\Var} \mid \BOOL{\itm{bool}}
|
|
|
+ \mid \VOID{} } \\
|
|
|
+\Exp &::=& \gray{ \Atm \mid \READ{} } \\
|
|
|
+ &\mid& \gray{ \NEG{\Atm} \mid \ADD{\Atm}{\Atm} } \\
|
|
|
+ &\mid& \gray{ \LET{\Var}{\Exp}{\Exp} } \\
|
|
|
+ &\mid& \gray{ \UNIOP{\key{'not}}{\Atm} } \\
|
|
|
+ &\mid& \gray{ \BINOP{\itm{cmp}}{\Atm}{\Atm} \mid \IF{\Exp}{\Exp}{\Exp} }\\
|
|
|
+ &\mid& \gray{ \LP\key{Collect}~\Int\RP \mid \LP\key{Allocate}~\Int~\Type\RP
|
|
|
+ \mid \LP\key{GlobalValue}~\Var\RP }\\
|
|
|
+ &\mid& \FUNREF{\Var} \mid \APPLY{\Atm}{\Atm\ldots}\\
|
|
|
+ \Def &::=& \gray{ \FUNDEF{\Var}{([\Var \code{:} \Type]\ldots)}{\Type}{\code{'()}}{\Exp} }\\
|
|
|
+R^{\dagger}_4 &::=& \gray{ \PROGRAMDEFS{\code{'()}}{\Def} }
|
|
|
+\end{array}
|
|
|
+\]
|
|
|
+\end{minipage}
|
|
|
+}
|
|
|
+\caption{$R_4^{\dagger}$ is $R_4$ in administrative normal form (ANF).}
|
|
|
+\label{fig:r4-anf-syntax}
|
|
|
+\end{figure}
|
|
|
|
|
|
|
|
|
\section{Explicate Control and the $C_3$ language}
|
|
@@ -7644,6 +7688,7 @@ apply this new function to all the function definitions.
|
|
|
\begin{figure}[tp]
|
|
|
\fbox{
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
+\small
|
|
|
\[
|
|
|
\begin{array}{lcl}
|
|
|
\Atm &::=& \gray{ \Int \mid \Var \mid \key{\#t} \mid \key{\#f} }
|
|
@@ -7674,7 +7719,7 @@ C_3 & ::= & \Def\ldots
|
|
|
\begin{figure}[tp]
|
|
|
\fbox{
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
- \small
|
|
|
+\small
|
|
|
\[
|
|
|
\begin{array}{lcl}
|
|
|
\Atm &::=& \gray{ \INT{\Int} \mid \VAR{\Var} \mid \BOOL{\itm{bool}} }\\
|
|
@@ -7682,19 +7727,19 @@ C_3 & ::= & \Def\ldots
|
|
|
\Exp &::= & \gray{ \Atm \mid \READ{} } \\
|
|
|
&\mid& \gray{ \NEG{\Atm} \mid \ADD{\Atm}{\Atm} }\\
|
|
|
&\mid& \gray{ \UNIOP{\key{not}}{\Atm} \mid \BINOP{\itm{cmp}}{\Atm}{\Atm} } \\
|
|
|
- &\mid& \gray{ (\key{Allocate} \,\itm{int}\,\itm{type}) } \\
|
|
|
+ &\mid& \gray{ \LP\key{Allocate} \,\itm{int}\,\itm{type}\RP } \\
|
|
|
&\mid& \gray{ \BINOP{\key{'vector-ref}}{\Atm}{\INT{\Int}} }\\
|
|
|
- &\mid& \gray{ (\key{Prim}~\key{'vector-set!}\,(\key{list}\,\Atm\,\INT{\Int}\,\Atm)) }\\
|
|
|
- &\mid& \gray{ (\key{GlobalValue} \,\Var) \mid (\key{Void}) }\\
|
|
|
+ &\mid& \gray{ \LP\key{Prim}~\key{'vector-set!}\,\LP\key{list}\,\Atm\,\INT{\Int}\,\Atm\RP\RP }\\
|
|
|
+ &\mid& \gray{ \LP\key{GlobalValue} \,\Var\RP \mid \LP\key{Void}\RP }\\
|
|
|
&\mid& \FUNREF{\itm{label}} \mid \CALL{\Atm}{\LP\Atm\ldots\RP} \\
|
|
|
\Stmt &::=& \gray{ \ASSIGN{\VAR{\Var}}{\Exp}
|
|
|
- \mid (\key{Collect} \,\itm{int}) } \\
|
|
|
+ \mid \LP\key{Collect} \,\itm{int}\RP } \\
|
|
|
\Tail &::= & \gray{ \RETURN{\Exp} \mid \SEQ{\Stmt}{\Tail}
|
|
|
\mid \GOTO{\itm{label}} } \\
|
|
|
&\mid& \gray{ \IFSTMT{\BINOP{\itm{cmp}}{\Atm}{\Atm}}{\GOTO{\itm{label}}}{\GOTO{\itm{label}}} }\\
|
|
|
&\mid& \TAILCALL{\Atm}{\Atm\ldots} \\
|
|
|
-\Def &::=& \DEF{\itm{label}}{([\Var\key{:}\Type]\ldots)}{\Type}{\itm{info}}{((\itm{label}\,\key{.}\,\Tail)\ldots)}\\
|
|
|
-C_3 & ::= & \PROGRAMDEFS{\itm{info}}{(\Def\ldots)}
|
|
|
+\Def &::=& \DEF{\itm{label}}{\LP[\Var\key{:}\Type]\ldots\RP}{\Type}{\itm{info}}{\LP\LP\itm{label}\,\key{.}\,\Tail\RP\ldots\RP}\\
|
|
|
+C_3 & ::= & \PROGRAMDEFS{\itm{info}}{\LP\Def\ldots\RP}
|
|
|
\end{array}
|
|
|
\]
|
|
|
\end{minipage}
|
|
@@ -8566,7 +8611,7 @@ $\Downarrow$
|
|
|
\begin{tikzpicture}[baseline=(current bounding box.center)]
|
|
|
\node (R4) at (0,2) {\large $R_4$};
|
|
|
\node (R4-2) at (3,2) {\large $R_4$};
|
|
|
-%\node (R4-3) at (6,2) {\large $R_4$};
|
|
|
+\node (R4-3) at (6,2) {\large $R_4$};
|
|
|
\node (F1-1) at (12,0) {\large $F_1$};
|
|
|
\node (F1-2) at (9,0) {\large $F_1$};
|
|
|
\node (F1-3) at (6,0) {\large $F_1$};
|
|
@@ -8582,25 +8627,25 @@ $\Downarrow$
|
|
|
\node (x86-2-1) at (3,-6) {\large $\text{x86}^{*}_3$};
|
|
|
\node (x86-2-2) at (6,-6) {\large $\text{x86}^{*}_3$};
|
|
|
|
|
|
-%% \path[->,bend left=15] (R4) edge [above] node
|
|
|
-%% {\ttfamily\footnotesize\color{red} type-check} (R4-2);
|
|
|
\path[->,bend left=15] (R4) edge [above] node
|
|
|
- {\ttfamily\footnotesize uniquify} (R4-2);
|
|
|
-\path[->,bend left=15] (R4-2) edge [right] node
|
|
|
+ {\ttfamily\footnotesize shrink} (R4-2);
|
|
|
+\path[->,bend left=15] (R4-2) edge [above] node
|
|
|
+ {\ttfamily\footnotesize uniquify} (R4-3);
|
|
|
+\path[->,bend left=15] (R4-3) edge [right] node
|
|
|
{\ttfamily\footnotesize reveal-functions} (F1-1);
|
|
|
\path[->,bend left=15] (F1-1) edge [below] node
|
|
|
{\ttfamily\footnotesize\color{red} convert-to-clos.} (F1-2);
|
|
|
\path[->,bend right=15] (F1-2) edge [above] node
|
|
|
- {\ttfamily\footnotesize limit-functions} (F1-3);
|
|
|
+ {\ttfamily\footnotesize limit-fun.} (F1-3);
|
|
|
\path[->,bend right=15] (F1-3) edge [above] node
|
|
|
{\ttfamily\footnotesize expose-alloc.} (F1-4);
|
|
|
\path[->,bend right=15] (F1-4) edge [above] node
|
|
|
{\ttfamily\footnotesize remove-complex.} (F1-5);
|
|
|
-\path[->] (F1-5) edge [left] node
|
|
|
+\path[->,bend right=15] (F1-5) edge [right] node
|
|
|
{\ttfamily\footnotesize explicate-control} (C3-2);
|
|
|
-\path[->,bend right=15] (C3-2) edge [left] node
|
|
|
+\path[->,bend left=15] (C3-2) edge [left] node
|
|
|
{\ttfamily\footnotesize select-instr.} (x86-2);
|
|
|
-\path[->,bend left=15] (x86-2) edge [left] node
|
|
|
+\path[->,bend right=15] (x86-2) edge [left] 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);
|
|
@@ -8608,7 +8653,8 @@ $\Downarrow$
|
|
|
{\ttfamily\footnotesize allocate-reg.} (x86-3);
|
|
|
\path[->,bend left=15] (x86-3) edge [above] node
|
|
|
{\ttfamily\footnotesize patch-instr.} (x86-4);
|
|
|
-\path[->,bend right=15] (x86-4) edge [left] node {\ttfamily\footnotesize print-x86} (x86-5);
|
|
|
+\path[->,bend left=15] (x86-4) edge [right] node
|
|
|
+ {\ttfamily\footnotesize print-x86} (x86-5);
|
|
|
\end{tikzpicture}
|
|
|
\caption{Diagram of the passes for $R_5$, a language with lexically-scoped
|
|
|
functions.}
|
|
@@ -8702,7 +8748,7 @@ operator in a direct call, then we say that the function
|
|
|
need to perform closure conversion on the function.
|
|
|
|
|
|
\begin{exercise}\normalfont
|
|
|
- Implement an auxilliary function for detecting which global
|
|
|
+ Implement an auxiliary function for detecting which global
|
|
|
functions escape. Using that function, implement an improved version
|
|
|
of closure conversion that does not apply closure conversion to
|
|
|
global functions that do not escape but instead compiles them as
|
|
@@ -8852,7 +8898,7 @@ in Figure~\ref{fig:r8-syntax}.
|
|
|
&\mid& \gray{ \VOID{} \mid \LP\key{HasType}~\Exp~\Type \RP
|
|
|
\mid \APPLY{\Exp}{\Exp\ldots} }\\
|
|
|
&\mid& \gray{ \LAMBDA{\LP\LS\Var\code{:}\Type\RS\ldots\RP}{\Type}{\Exp} }\\
|
|
|
- &\mid& \SETBANG{\Var}{\Exp} \mid \BEGIN{\Exp\ldots}{\Exp}
|
|
|
+ &\mid& \SETBANG{\Var}{\Exp} \mid \BEGIN{\LP\Exp\ldots\RP}{\Exp}
|
|
|
\mid \WHILE{\Exp}{\Exp} \\
|
|
|
\Def &::=& \gray{ \FUNDEF{\Var}{\LP\LS\Var \code{:} \Type\RS\ldots\RP}{\Type}{\code{'()}}{\Exp} }\\
|
|
|
R_5 &::=& \gray{ \PROGRAMDEFSEXP{\code{'()}}{\LP\Def\ldots\RP}{\Exp} }
|
|
@@ -8865,6 +8911,9 @@ in Figure~\ref{fig:r8-syntax}.
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
+% TODO: type checker and interpreter for $R_8$.
|
|
|
+
|
|
|
+
|
|
|
At first glance, the translation of these language features to x86
|
|
|
seems to be trivial because the $C_3$ intermediate language already
|
|
|
supports all of the ingredients that we need: assignment, \code{goto},
|
|
@@ -8900,7 +8949,7 @@ closure. Thus, if we naively add support for assignment to our current
|
|
|
compiler, the output of this program would be \code{32}.
|
|
|
|
|
|
A first attempt at solving this problem would be to save a pointer to
|
|
|
-\code{x} in the closure and change the occurences of \code{x} inside
|
|
|
+\code{x} in the closure and change the occurrences of \code{x} inside
|
|
|
the lambda to dereference the pointer. Of course, this would require
|
|
|
assigning \code{x} to the stack and not to a register. However, the
|
|
|
problem goes a bit deeper. Consider the following example in which we
|
|
@@ -8998,8 +9047,8 @@ Next we might try to analyze \code{block5} or \code{block7}, but
|
|
|
\code{block5} jumps to \code{block7} and vice versa, so it seems that
|
|
|
we are stuck.
|
|
|
|
|
|
-The way out of this impass comes from the realization that one can
|
|
|
-perfom liveness analysis starting with an empty live-after set to
|
|
|
+The way out of this impasse comes from the realization that one can
|
|
|
+perform liveness analysis starting with an empty live-after set to
|
|
|
compute an under-approximation of the live-before set. By
|
|
|
\emph{under-approximation}, we mean that the set only contains
|
|
|
variables that are really live, but it may be missing some. Next, the
|
|
@@ -9041,16 +9090,16 @@ block8: {rsp, sum1}
|
|
|
\end{center}
|
|
|
|
|
|
For the second round, the live-after for \code{mainstart} is the
|
|
|
-current live-before for \code{block5}, which is \code{\{i2\}}. So
|
|
|
-the liveness analysis for \code{mainstart} computes the empty set. The
|
|
|
-live-after for \code{block5} is the union of the live-before's for
|
|
|
+current live-before for \code{block5}, which is \code{\{i2\}}. So the
|
|
|
+liveness analysis for \code{mainstart} computes the empty set. The
|
|
|
+live-after for \code{block5} is the union of the live-before sets for
|
|
|
\code{block7} and \code{block8}, which is \code{\{i2 , rsp, sum1\}}.
|
|
|
So the liveness analysis for \code{block5} computes \code{\{i2 , rsp,
|
|
|
sum1\}}. The live-after for \code{block7} is the live-before for
|
|
|
\code{block5} (from the previous iteration), which is \code{\{i2\}}.
|
|
|
-So the liveness analysis for \code{block7} remains \code{\{i2, sum1\}}.
|
|
|
-Together these yield the following approximation $m_2$ of the
|
|
|
-live-before sets.
|
|
|
+So the liveness analysis for \code{block7} remains \code{\{i2,
|
|
|
+ sum1\}}. Together these yield the following approximation $m_2$ of
|
|
|
+the live-before sets.
|
|
|
\begin{center}
|
|
|
\begin{lstlisting}
|
|
|
mainstart: {}
|
|
@@ -9059,7 +9108,7 @@ block7: {i2, sum1}
|
|
|
block8: {rsp, sum1}
|
|
|
\end{lstlisting}
|
|
|
\end{center}
|
|
|
-In the preceeding iteration, only \code{block5} changed, so we can
|
|
|
+In the preceding iteration, only \code{block5} changed, so we can
|
|
|
limit our attention to \code{mainstart} and \code{block7}, the two
|
|
|
blocks that jump to \code{block5}. As a result, the live-before sets
|
|
|
for \code{mainstart} and \code{block7} are updated to include
|
|
@@ -9092,7 +9141,7 @@ operator takes two lattice elements and combines their information,
|
|
|
i.e., it produces the least upper bound of the two.\index{least upper
|
|
|
bound}
|
|
|
|
|
|
-A dataflow analysis typicaly involves two lattices: one lattice to
|
|
|
+A dataflow analysis typically involves two lattices: one lattice to
|
|
|
represent abstract states and another lattice that aggregates the
|
|
|
abstract states of all the blocks in the control-flow graph. For
|
|
|
liveness analysis, an abstract state is a set of locations. We form
|
|
@@ -9102,11 +9151,11 @@ set, and the join operator to be set union.
|
|
|
%
|
|
|
We form a second lattice $M$ by taking its elements to be mappings
|
|
|
from the block labels to sets of locations (elements of $L$). We
|
|
|
-order the mappings pointwise, using the ordering of $L$. So given any
|
|
|
+order the mappings point-wise, using the ordering of $L$. So given any
|
|
|
two mappings $m_i$ and $m_j$, $m_i \sqsubseteq_M m_j$ when $m_i(\ell)
|
|
|
\subseteq m_j(\ell)$ for every block label $\ell$ in the program. The
|
|
|
bottom element of $M$ is the mapping $\bot_M$ that sends every label
|
|
|
-to the emptyset, i.e., $\bot_M(\ell) = \emptyset$.
|
|
|
+to the empty set, i.e., $\bot_M(\ell) = \emptyset$.
|
|
|
|
|
|
We can think of one iteration of liveness analysis as being a function
|
|
|
$f$ on the lattice $M$. It takes a mapping as input and computes a new
|
|
@@ -9154,8 +9203,8 @@ generic work list algorithm (Figure~\ref{fig:generic-dataflow}).
|
|
|
The algorithm has four parameters: the control-flow graph \code{G}, a
|
|
|
function \code{transfer} that applies the analysis to one block, the
|
|
|
\code{bottom} and \code{join} operator for the lattice of abstract
|
|
|
-staties. The algorithm begins by creating the bottom mapping,
|
|
|
-represented by hashtable. It then pushes all of the nodes in the
|
|
|
+states. The algorithm begins by creating the bottom mapping,
|
|
|
+represented by a hash table. It then pushes all of the nodes in the
|
|
|
control-flow graph onto the work list (a queue). The algorithm repeats
|
|
|
the \code{while} loop as long as there are items in the work list. In
|
|
|
each iteration, a node is popped from the work list and processed. The
|
|
@@ -9242,11 +9291,11 @@ example is as follows.
|
|
|
|
|
|
\paragraph{Assigned \& Free}
|
|
|
|
|
|
-We recommend defining an auxilliary function named
|
|
|
+We recommend defining an auxiliary function named
|
|
|
\code{assigned\&free} that takes an expression and simultaneously
|
|
|
computes 1) a set of assigned variables $A$, 2) a set $F$ of variables
|
|
|
that occur free within lambda's, and 3) a new version of the
|
|
|
-expression that records which bound variables occured in the
|
|
|
+expression that records which bound variables occurred in the
|
|
|
intersection of $A$ and $F$. You can use the struct
|
|
|
\code{AssignedFree} to do this. Consider the case for
|
|
|
$\LET{x}{\itm{rhs}}{\itm{body}}$. Suppose the the recursive call on
|
|
@@ -9360,54 +9409,237 @@ function \code{f}.
|
|
|
\section{Remove Complex Operands}
|
|
|
\label{sec:rco-loop}
|
|
|
|
|
|
+The three new language forms, \code{while}, \code{set!}, and
|
|
|
+\code{begin} need to be categorized as atomic or complex expressions,
|
|
|
+as do their subexpressions. They are all complex and their
|
|
|
+subexpressions are all allowed to be complex.
|
|
|
+Figure~\ref{fig:r4-anf-syntax} defines the output language
|
|
|
+$R_4^{\dagger}$ of this pass.
|
|
|
|
|
|
-TODO: define the output grammar
|
|
|
+\begin{figure}[tp]
|
|
|
+\centering
|
|
|
+\fbox{
|
|
|
+\begin{minipage}{0.96\textwidth}
|
|
|
+\small
|
|
|
+\[
|
|
|
+\begin{array}{rcl}
|
|
|
+\Atm &::=& \gray{ \INT{\Int} \mid \VAR{\Var} \mid \BOOL{\itm{bool}}
|
|
|
+ \mid \VOID{} } \\
|
|
|
+\Exp &::=& \ldots \mid \gray{ \LET{\Var}{\Exp}{\Exp} } \\
|
|
|
+ &\mid& \WHILE{\Exp}{\Exp} \mid \SETBANG{\Var}{\Exp}
|
|
|
+ \mid \BEGIN{\LP\Exp\ldots\RP}{\Exp} \\
|
|
|
+\Def &::=& \gray{ \FUNDEF{\Var}{([\Var \code{:} \Type]\ldots)}{\Type}{\code{'()}}{\Exp} }\\
|
|
|
+R^{\dagger}_8 &::=& \gray{ \PROGRAMDEFS{\code{'()}}{\Def} }
|
|
|
+\end{array}
|
|
|
+\]
|
|
|
+\end{minipage}
|
|
|
+}
|
|
|
+\caption{$R_8^{\dagger}$ is $R_8$ in administrative normal form (ANF).}
|
|
|
+\label{fig:r8-anf-syntax}
|
|
|
+\end{figure}
|
|
|
|
|
|
+As usual, when a complex expression appears in a grammar position that
|
|
|
+needs to be atomic, such as the argument of a primitive operator, we
|
|
|
+must introduce a temporary variable and bind it to the complex
|
|
|
+expression. This approach applies, unchanged, to handle the new
|
|
|
+language forms. For example, in the following code there are two
|
|
|
+\code{begin} expressions appearing as arguments to \code{+}. The
|
|
|
+output of \code{rco-exp} is shown below, in which the \code{begin}
|
|
|
+expression have been bound to temporary variables. Recall that
|
|
|
+\code{let} expressions in $R_8^{\dagger}$ are allowed to have
|
|
|
+arbitrary expressions in their right-hand-side expression, so it is
|
|
|
+fine to place \code{begin} there.
|
|
|
|
|
|
\begin{lstlisting}
|
|
|
(let ([x0 10])
|
|
|
(let ([y1 0])
|
|
|
(+ (+ (begin (set! y1 (read)) x0)
|
|
|
- (begin (set! x0 (read)) y1))
|
|
|
+ (begin (set! x0 (read)) y1))
|
|
|
x0)))
|
|
|
|$\Rightarrow$|
|
|
|
-(define (main) : Integer
|
|
|
- (let ([x0 10])
|
|
|
- (let ([y1 0])
|
|
|
- (let ([tmp2 (begin
|
|
|
- (set! y1 (read))
|
|
|
- x0)])
|
|
|
- (let ([tmp3 (begin
|
|
|
- (set! x0 (read))
|
|
|
- y1)])
|
|
|
- (let ([tmp4 (+ tmp2 tmp3)])
|
|
|
- (+ tmp4 x0)))))))
|
|
|
+(let ([x0 10])
|
|
|
+ (let ([y1 0])
|
|
|
+ (let ([tmp2 (begin (set! y1 (read)) x0)])
|
|
|
+ (let ([tmp3 (begin (set! x0 (read)) y1)])
|
|
|
+ (let ([tmp4 (+ tmp2 tmp3)])
|
|
|
+ (+ tmp4 x0))))))
|
|
|
\end{lstlisting}
|
|
|
|
|
|
+\section{Explicate Control}
|
|
|
+\label{sec:explicate-loop}
|
|
|
|
|
|
+Recall that in the \code{explicate-control} pass we define one helper
|
|
|
+function for each kind of position in the program. For the $R_1$
|
|
|
+language of integers and variables we needed kinds of positions:
|
|
|
+assignment and tail. The \code{if} expressions of $R_2$ introduced
|
|
|
+predicate positions. For $R_8$, the \code{begin} expression introduces
|
|
|
+yet another kind of position: effect position. Except for the last
|
|
|
+subexpression, the subexpressions inside a \code{begin} are evaluated
|
|
|
+only for their effect. Their result values are discarded. We can
|
|
|
+generate better code by taking this fact into account.
|
|
|
+
|
|
|
+The output language of \code{explicate-control} is $C_7$
|
|
|
+(Figure~\ref{fig:c7-syntax}), which is nearly identical to $C_3$. The
|
|
|
+only difference is that \code{Call}, \code{vector-set!}, and
|
|
|
+\code{read} may also appear as statements.
|
|
|
|
|
|
+\begin{figure}[tp]
|
|
|
+\fbox{
|
|
|
+\begin{minipage}{0.96\textwidth}
|
|
|
+\small
|
|
|
+\[
|
|
|
+\begin{array}{lcl}
|
|
|
+\Stmt &::=& \gray{ \ASSIGN{\VAR{\Var}}{\Exp}
|
|
|
+ \mid \LP\key{Collect} \,\itm{int}\RP } \\
|
|
|
+ &\mid& \CALL{\Atm}{\LP\Atm\ldots\RP} \mid \READ{}\\
|
|
|
+ &\mid& \LP\key{Prim}~\key{'vector-set!}\,\LP\key{list}\,\Atm\,\INT{\Int}\,\Atm\RP\RP \\
|
|
|
+\Def &::=& \DEF{\itm{label}}{\LP\LS\Var\key{:}\Type\RS\ldots\RP}{\Type}{\itm{info}}{\LP\LP\itm{label}\,\key{.}\,\Tail\RP\ldots\RP}\\
|
|
|
+C_3 & ::= & \PROGRAMDEFS{\itm{info}}{\LP\Def\ldots\RP}
|
|
|
+\end{array}
|
|
|
+\]
|
|
|
+\end{minipage}
|
|
|
+}
|
|
|
+\caption{The abstract syntax of $C_7$, extending $C_3$ (Figure~\ref{fig:c3-syntax}).}
|
|
|
+\label{fig:c7-syntax}
|
|
|
+\end{figure}
|
|
|
|
|
|
+The new auxiliary function \code{explicate-effect} takes an expression
|
|
|
+(in an effect position) and a promise of a continuation block. The
|
|
|
+function returns a promise for a $\Tail$ that includes the generated
|
|
|
+code for the input expression followed by the continuation block. If
|
|
|
+the expression is obviously pure, that is, never causes side effects,
|
|
|
+then the expression can be removed, so the result is just the
|
|
|
+continuation block.
|
|
|
+%
|
|
|
+The $\WHILE{\itm{cnd}}{\itm{body}}$ loop is the most interesting case.
|
|
|
+First, you will need a fresh label $\itm{loop}$ for the top of the
|
|
|
+loop. Recursively process the \itm{body} (in effect position) with
|
|
|
+the a \code{goto} to $\itm{loop}$ as the continuation, producing
|
|
|
+\itm{body'}. Next, process the \itm{cnd} (in predicate position) with
|
|
|
+\itm{body'} as the then-branch and the continuation block as the
|
|
|
+else-branch. The result should be added to the control-flow graph with
|
|
|
+the label \itm{loop}. The result for the whole \code{while} loop is a
|
|
|
+\code{goto} to the \itm{loop} label. Note that the loop should only be
|
|
|
+added to the control-flow graph if the loop is indeed used, which can
|
|
|
+be accomplished using \code{delay}.
|
|
|
+
|
|
|
+The auxiliary functions for tail, assignment, and predicate positions
|
|
|
+need to be updated. The three new language forms, \code{while},
|
|
|
+\code{set!}, and \code{begin}, can appear in assignment and tail
|
|
|
+positions. Only \code{begin} may appear in predicate positions; the
|
|
|
+other two have result type \code{Void}.
|
|
|
|
|
|
-\section{Explicate Control}
|
|
|
-\label{sec:explicate-loop}
|
|
|
+\section{Select Instructions}
|
|
|
+\label{sec:select-instructions-loop}
|
|
|
|
|
|
+Only three small additions are needed in the
|
|
|
+\code{select-instructions} pass to handle the changes to $C_7$. That
|
|
|
+is, \code{Call}, \code{read}, and \code{vector-set!} may now appear as
|
|
|
+stand-alone statements instead of only appearing on the right-hand
|
|
|
+side of an assignment statement. The code generation is nearly
|
|
|
+identical; just leave off the instruction for moving the result into
|
|
|
+the left-hand side.
|
|
|
|
|
|
\section{Register Allocation}
|
|
|
\label{sec:register-allocation-loop}
|
|
|
|
|
|
+As discussed in Section~\ref{sec:dataflow-analysis}, the presence of
|
|
|
+loops in $R_8$ means that the control-flow graphs may contain cycles,
|
|
|
+which complicates the liveness analysis needed for register
|
|
|
+allocation.
|
|
|
|
|
|
-%\section{Remove Jumps}
|
|
|
-%\label{sec:remove-jumps-loop}
|
|
|
+\subsection{Liveness Analysis}
|
|
|
+\label{sec:liveness-analysis-r8}
|
|
|
|
|
|
+We recommend using the generic \code{analyze-dataflow} function that
|
|
|
+was presented at the end of Section~\ref{sec:dataflow-analysis} to
|
|
|
+perform liveness analysis, replacing the code in
|
|
|
+\code{uncover-live-CFG} that processed the basic blocks in topological
|
|
|
+order (Section~\ref{sec:liveness-analysis-r2}).
|
|
|
|
|
|
-\section{Select Instructions}
|
|
|
-\label{sec:select-instructions-loop}
|
|
|
+The \code{analyze-dataflow} function has four parameters.
|
|
|
+\begin{enumerate}
|
|
|
+\item The first parameter \code{G} should be a directed graph from the
|
|
|
+ \code{racket/graph} package (see the sidebar in
|
|
|
+ Section~\ref{sec:build-interference}) that represents the
|
|
|
+ control-flow graph.
|
|
|
+\item The second parameter \code{transfer} is a function that applies
|
|
|
+ liveness analysis to a basic block. It takes two parameters: the
|
|
|
+ label for the block to analyze and the live-after set for that
|
|
|
+ block. The transfer function should return the live-before set for
|
|
|
+ the block. Also, as a side-effect, it should update the block's
|
|
|
+ $\itm{info}$ with the liveness information for each instruction. To
|
|
|
+ implement the \code{transfer} function, you should be able to reuse
|
|
|
+ the code you already have for analyzing basic blocks.
|
|
|
+\item The third and fourth parameters of \code{analyze-dataflow} are
|
|
|
+ \code{bottom} and \code{join} for the lattice of abstract states,
|
|
|
+ i.e. sets of locations. The bottom of the lattice is the empty set
|
|
|
+ \code{(set)} and the join operator is \code{set-union}.
|
|
|
+\end{enumerate}
|
|
|
|
|
|
|
|
|
+\begin{figure}[p]
|
|
|
+\begin{tikzpicture}[baseline=(current bounding box.center)]
|
|
|
+\node (R4) at (0,2) {\large $R_8$};
|
|
|
+\node (R4-2) at (3,2) {\large $R_8$};
|
|
|
+\node (R4-3) at (6,2) {\large $R_8$};
|
|
|
+\node (R4-4) at (9,2) {\large $R_8$};
|
|
|
+\node (F1-1) at (12,0) {\large $F_1$};
|
|
|
+\node (F1-2) at (9,0) {\large $F_1$};
|
|
|
+\node (F1-3) at (6,0) {\large $F_1$};
|
|
|
+\node (F1-4) at (3,0) {\large $F_1$};
|
|
|
+\node (F1-5) at (0,0) {\large $F_1$};
|
|
|
+\node (C3-2) at (3,-2) {\large $C_3$};
|
|
|
+
|
|
|
+\node (x86-2) at (3,-4) {\large $\text{x86}^{*}_3$};
|
|
|
+\node (x86-3) at (6,-4) {\large $\text{x86}^{*}_3$};
|
|
|
+\node (x86-4) at (9,-4) {\large $\text{x86}^{*}_3$};
|
|
|
+\node (x86-5) at (9,-6) {\large $\text{x86}^{\dagger}_3$};
|
|
|
|
|
|
+\node (x86-2-1) at (3,-6) {\large $\text{x86}^{*}_3$};
|
|
|
+\node (x86-2-2) at (6,-6) {\large $\text{x86}^{*}_3$};
|
|
|
+
|
|
|
+%% \path[->,bend left=15] (R4) edge [above] node
|
|
|
+%% {\ttfamily\footnotesize\color{red} type-check} (R4-2);
|
|
|
+\path[->,bend left=15] (R4) edge [above] node
|
|
|
+ {\ttfamily\footnotesize shrink} (R4-2);
|
|
|
+\path[->,bend left=15] (R4-2) edge [above] node
|
|
|
+ {\ttfamily\footnotesize uniquify} (R4-3);
|
|
|
+\path[->,bend left=15] (R4-3) edge [above] node
|
|
|
+ {\ttfamily\footnotesize\color{red} convert-assignments} (R4-4);
|
|
|
+\path[->,bend left=15] (R4-4) edge [left] node
|
|
|
+ {\ttfamily\footnotesize reveal-functions} (F1-1);
|
|
|
+\path[->,bend left=15] (F1-1) edge [below] node
|
|
|
+ {\ttfamily\footnotesize convert-to-clos.} (F1-2);
|
|
|
+\path[->,bend right=15] (F1-2) edge [above] node
|
|
|
+ {\ttfamily\footnotesize limit-fun.} (F1-3);
|
|
|
+\path[->,bend right=15] (F1-3) edge [above] node
|
|
|
+ {\ttfamily\footnotesize expose-alloc.} (F1-4);
|
|
|
+\path[->,bend right=15] (F1-4) edge [above] node
|
|
|
+ {\ttfamily\footnotesize\color{red} remove-complex.} (F1-5);
|
|
|
+\path[->,bend right=15] (F1-5) edge [right] node
|
|
|
+ {\ttfamily\footnotesize\color{red} explicate-control} (C3-2);
|
|
|
+\path[->,bend left=15] (C3-2) edge [left] node
|
|
|
+ {\ttfamily\footnotesize\color{red} select-instr.} (x86-2);
|
|
|
+\path[->,bend right=15] (x86-2) edge [left] node
|
|
|
+ {\ttfamily\footnotesize\color{red} 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 [left] 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);
|
|
|
+\end{tikzpicture}
|
|
|
+ \caption{Diagram of the passes for $R_8$ (loops and assignment).}
|
|
|
+\label{fig:R8-passes}
|
|
|
+\end{figure}
|
|
|
|
|
|
+Figure~\ref{fig:R8-passes} provides an overview of all the passes needed
|
|
|
+for the compilation of $R_8$.
|
|
|
|
|
|
|
|
|
+% TODO: challenge assignment
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
\chapter{Dynamic Typing}
|
|
@@ -10434,11 +10666,11 @@ registers.
|
|
|
%% LocalWords: Sarkar lcl Matz aa representable Chez Ph Dan's nano
|
|
|
%% LocalWords: fk bh Siek plt uq Felleisen Bor Yuh ASTs AST Naur eq
|
|
|
%% LocalWords: BNF fixnum datatype arith prog backquote quasiquote
|
|
|
-%% LocalWords: ast Reynold's reynolds interp cond fx evaluator
|
|
|
+%% LocalWords: ast Reynold's reynolds interp cond fx evaluator jane
|
|
|
%% LocalWords: quasiquotes pe nullary unary rcl env lookup gcc rax
|
|
|
%% LocalWords: addq movq callq rsp rbp rbx rcx rdx rsi rdi subq nx
|
|
|
%% LocalWords: negq pushq popq retq globl Kernighan uniquify lll ve
|
|
|
-%% LocalWords: allocator gensym env subdirectory scm rkt tmp lhs
|
|
|
+%% LocalWords: allocator gensym env subdirectory scm rkt tmp lhs Tt
|
|
|
%% LocalWords: runtime Liveness liveness undirected Balakrishnan je
|
|
|
%% LocalWords: Rosen DSATUR SDO Gebremedhin Omari morekeywords cnd
|
|
|
%% LocalWords: fullflexible vertices Booleans Listof Pairof thn els
|
|
@@ -10461,4 +10693,11 @@ registers.
|
|
|
% LocalWords: mainconclusion Cardelli bodyT fvs clos fvts subtype uj
|
|
|
% LocalWords: polymorphism untyped elts tys tagof Vectorof tyeq orq
|
|
|
% LocalWords: andq untagged Shao inlining ebp jge setle setg setge
|
|
|
-% LocalWords: struct symtab
|
|
|
+% LocalWords: struct symtab Friedman's MacOS Nystrom alist sam kate
|
|
|
+% LocalWords: alists arity github unordered pqueue exprs ret param
|
|
|
+% LocalWords: tyerr bytereg dh dl JmpIf HasType Osterlund Jacek TODO
|
|
|
+% LocalWords: Gamari GlobalValue ProgramDefsExp prm ProgramDefs vn
|
|
|
+% LocalWords: FunRef TailCall tailjmp IndirectCallq TailJmp Gilray
|
|
|
+% LocalWords: dereference unbox Dataflow versa dataflow Kildall rhs
|
|
|
+% LocalWords: Kleene enqueue dequeue AssignedFree FV cnvt SetBang tg
|
|
|
+% LocalWords: ValueOf typechecker
|