|
@@ -4492,7 +4492,7 @@ checking and when we uncover local variables. The type checker in
|
|
|
Figure~\ref{fig:typecheck-R3} not only computes the type of an
|
|
|
expression, it also wraps every sub-expression $e$ with the form
|
|
|
$(\key{has-type}\; e\; T)$, where $T$ is $e$'s type. Subsequently, in
|
|
|
-the \code{uncover-locals} pass (Section~\ref{sec:uncover-locals-gc})
|
|
|
+the \code{uncover-locals} pass (Section~\ref{sec:uncover-locals-r3})
|
|
|
this type information is propagated to all variables (including the
|
|
|
temporaries generated by \code{remove-complex-opera*}).
|
|
|
|
|
@@ -5139,8 +5139,8 @@ the register allocator.
|
|
|
\mid (\key{cmpq} \; \Arg\; \Arg) \mid (\key{set}\itm{cc} \; \Arg) } \\
|
|
|
&\mid& \gray{ (\key{movzbq}\;\Arg\;\Arg)
|
|
|
\mid (\key{jmp} \; \itm{label})
|
|
|
- \mid (\key{jmp-if}\itm{cc} \; \itm{label})
|
|
|
- \mid (\key{label} \; \itm{label}) } \\
|
|
|
+ \mid (\key{jmp-if}\itm{cc} \; \itm{label})}\\
|
|
|
+ &\mid& \gray{(\key{label} \; \itm{label}) } \\
|
|
|
x86_2 &::= & \gray{ (\key{program} \;\itm{info} \;(\key{type}\;\itm{type})\; \Instr^{+}) }
|
|
|
\end{array}
|
|
|
\]
|
|
@@ -5827,7 +5827,7 @@ function name differently than the use of a local variable; we need to
|
|
|
use \code{leaq} to convert the function name (a label in x86) to an
|
|
|
address in a register. Thus, it is a good idea to create a new pass
|
|
|
that changes function references from just a symbol $f$ to
|
|
|
-\code{(function-ref $f$)}. A good name for this pass is
|
|
|
+\code{(fun-ref $f$)}. A good name for this pass is
|
|
|
\code{reveal-functions} and the output language, $F_1$, is defined in
|
|
|
Figure~\ref{fig:f1-syntax}.
|
|
|
|
|
@@ -5847,7 +5847,7 @@ Figure~\ref{fig:f1-syntax}.
|
|
|
(\key{vector-ref}\;\Exp\;\Int)} \\
|
|
|
&\mid& \gray{(\key{vector-set!}\;\Exp\;\Int\;\Exp)\mid (\key{void}) \mid
|
|
|
(\key{app}\; \Exp \; \Exp^{*})} \\
|
|
|
- &\mid& (\key{function-ref}\, \itm{label}) \\
|
|
|
+ &\mid& (\key{fun-ref}\, \itm{label}) \\
|
|
|
\Def &::=& \gray{(\key{define}\; (\itm{label} \; [\Var \key{:} \Type]^{*}) \key{:} \Type \; \Exp)} \\
|
|
|
F_1 &::=& \gray{(\key{program}\;\itm{info} \; \Def^{*})}
|
|
|
\end{array}
|
|
@@ -5868,7 +5868,7 @@ Placing this pass after \code{uniquify} is a good idea, because it
|
|
|
will make sure that there are no local variables and functions that
|
|
|
share the same name. On the other hand, \code{reveal-functions} needs
|
|
|
to come before the \code{explicate-control} pass because that pass
|
|
|
-will help us compile \code{function-ref} into assignment statements.
|
|
|
+will help us compile \code{fun-ref} into assignment statements.
|
|
|
|
|
|
\section{Limit Functions}
|
|
|
\label{sec:limit-functions-r4}
|
|
@@ -5901,6 +5901,18 @@ which $i>5$ must be replaced with a \code{vector-ref}.
|
|
|
\section{Remove Complex Operators and Operands}
|
|
|
\label{sec:rco-r4}
|
|
|
|
|
|
+The primary decisions to make for this pass is whether to classify
|
|
|
+\code{fun-ref} and \code{app} as either simple or complex
|
|
|
+expressions. Recall that a simple expression will eventually end up as
|
|
|
+just an ``immediate'' argument of an x86 instruction. Function
|
|
|
+application will be translated to a sequence of instructions, so
|
|
|
+\code{app} must be classified as complex expression. Regarding
|
|
|
+\code{fun-ref}, as discussed above, the function label needs to
|
|
|
+be converted to an address using the \code{leaq} instruction. Thus,
|
|
|
+even though \code{fun-ref} 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}.
|
|
|
|
|
|
\section{Explicate Control and the $C_3$ language}
|
|
|
\label{sec:explicate-control-r4}
|
|
@@ -5908,13 +5920,13 @@ which $i>5$ must be replaced with a \code{vector-ref}.
|
|
|
Figure~\ref{fig:c3-syntax} defines the syntax for $C_3$, the output of
|
|
|
\key{explicate-control}. The three mutually recursive functions for
|
|
|
this pass, for assignment, tail, and predicate contexts, must all be
|
|
|
-updated with cases for \code{function-ref} and \code{app}. In
|
|
|
+updated with cases for \code{fun-ref} and \code{app}. In
|
|
|
assignment and predicate contexts, \code{app} becomes \code{call},
|
|
|
whereas in tail position \code{app} becomes \code{tailcall}. We
|
|
|
recommend defining a new function for processing function definitions.
|
|
|
This code is similar to the case for \code{program} in $R_3$. The
|
|
|
top-level \code{explicate-control} function that handles the
|
|
|
-\code{progarm} form of $R_4$ can then apply this new function to all
|
|
|
+\code{program} form of $R_4$ can then apply this new function to all
|
|
|
the function definitions.
|
|
|
|
|
|
\begin{figure}[tp]
|
|
@@ -5923,14 +5935,14 @@ the function definitions.
|
|
|
\[
|
|
|
\begin{array}{lcl}
|
|
|
\Arg &::=& \gray{ \Int \mid \Var \mid \key{\#t} \mid \key{\#f} }
|
|
|
- \mid (\key{function-ref}\,\itm{label})\\
|
|
|
+ \\
|
|
|
\itm{cmp} &::= & \gray{ \key{eq?} \mid \key{<} } \\
|
|
|
\Exp &::= & \gray{ \Arg \mid (\key{read}) \mid (\key{-}\;\Arg) \mid (\key{+} \; \Arg\;\Arg)
|
|
|
\mid (\key{not}\;\Arg) \mid (\itm{cmp}\;\Arg\;\Arg) } \\
|
|
|
&\mid& \gray{ (\key{allocate}\,\Int\,\Type)
|
|
|
\mid (\key{vector-ref}\, \Arg\, \Int) } \\
|
|
|
&\mid& \gray{ (\key{vector-set!}\,\Arg\,\Int\,\Arg) \mid (\key{global-value} \,\itm{name}) \mid (\key{void}) } \\
|
|
|
- &\mid& (\key{call} \,\Arg\,\Arg^{*}) \\
|
|
|
+ &\mid& (\key{fun-ref}\,\itm{label}) \mid (\key{call} \,\Arg\,\Arg^{*}) \\
|
|
|
\Stmt &::=& \gray{ \ASSIGN{\Var}{\Exp} \mid \RETURN{\Exp}
|
|
|
\mid (\key{collect} \,\itm{int}) }\\
|
|
|
\Tail &::= & \gray{\RETURN{\Exp} \mid (\key{seq}\;\Stmt\;\Tail)} \\
|
|
@@ -5959,43 +5971,9 @@ should be similar to the case for \code{program} in $C_2$.
|
|
|
\section{Select Instructions}
|
|
|
\label{sec:select-r4}
|
|
|
|
|
|
-\margincomment{\scriptsize To do: discuss the need to push and
|
|
|
- pop call-live pointers (vectors and functions)
|
|
|
- to the root stack \\ --Jeremy}
|
|
|
-
|
|
|
-
|
|
|
-Because each \code{function-ref} needs to eventually become an
|
|
|
-\code{leaq} instruction, it first needs to become an assignment
|
|
|
-statement so there is a left-hand side in which to put the
|
|
|
-result. This can be handled easily in the \code{flatten} pass by
|
|
|
-categorizing \code{function-ref} as a complex expression. Then, in
|
|
|
-the \code{select-instructions} pass, an assignment of
|
|
|
-\code{function-ref} becomes a \code{leaq} instruction as follows: \\
|
|
|
-\begin{tabular}{lll}
|
|
|
-\begin{minipage}{0.45\textwidth}
|
|
|
-\begin{lstlisting}
|
|
|
- (assign |$\itm{lhs}$| (function-ref |$f$|))
|
|
|
-\end{lstlisting}
|
|
|
-\end{minipage}
|
|
|
-&
|
|
|
-$\Rightarrow$
|
|
|
-&
|
|
|
-\begin{minipage}{0.4\textwidth}
|
|
|
-\begin{lstlisting}
|
|
|
-(leaq (function-ref |$f$|) |$\itm{lhs}$|)
|
|
|
-\end{lstlisting}
|
|
|
-\end{minipage}
|
|
|
-\end{tabular} \\
|
|
|
-%
|
|
|
-Note that in the syntax for $C_3$, tail calls are statements, not
|
|
|
-expressions. Once we perform a tail call, we do not ever expect it to
|
|
|
-return a value to us, and \code{select-instructions} therefore should
|
|
|
-handle \code{call} and \code{tailcall} forms differently.
|
|
|
-
|
|
|
The output of select instructions is a program in the x86$_3$
|
|
|
language, whose syntax is defined in Figure~\ref{fig:x86-3}.
|
|
|
|
|
|
-
|
|
|
\begin{figure}[tp]
|
|
|
\fbox{
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
@@ -6005,6 +5983,7 @@ language, whose syntax is defined in Figure~\ref{fig:x86-3}.
|
|
|
\mid (\key{deref}\,\itm{register}\,\Int) } \\
|
|
|
&\mid& \gray{ (\key{byte-reg}\; \itm{register})
|
|
|
\mid (\key{global-value}\; \itm{name}) } \\
|
|
|
+ &\mid& (\key{fun-ref}\; \itm{label})\\
|
|
|
\itm{cc} & ::= & \gray{ \key{e} \mid \key{l} \mid \key{le} \mid \key{g} \mid \key{ge} } \\
|
|
|
\Instr &::=& \gray{ (\key{addq} \; \Arg\; \Arg) \mid
|
|
|
(\key{subq} \; \Arg\; \Arg) \mid
|
|
@@ -6019,11 +5998,11 @@ language, whose syntax is defined in Figure~\ref{fig:x86-3}.
|
|
|
\mid (\key{jmp} \; \itm{label})
|
|
|
\mid (\key{j}\itm{cc} \; \itm{label})
|
|
|
\mid (\key{label} \; \itm{label}) } \\
|
|
|
- &\mid& (\key{indirect-callq}\;\Arg ) \mid (\key{indirect-jmp}\;\Arg) \\
|
|
|
+ &\mid& (\key{indirect-callq}\;\Arg ) \mid (\key{tail-jmp}\;\Arg) \\
|
|
|
&\mid& (\key{leaq}\;\Arg\;\Arg)\\
|
|
|
-\Def &::= & (\key{define} \; (\itm{label}) \;\itm{int} \;\itm{info}\; \Instr^{+})\\
|
|
|
-x86_3 &::= & (\key{program} \;\itm{info} \;(\key{type}\;\itm{type})\;
|
|
|
- (\key{defines}\,\Def^{*}) \; \Instr^{+})
|
|
|
+\Block &::= & \gray{(\key{block} \;\itm{info}\; \Instr^{+})} \\
|
|
|
+\Def &::= & (\key{define} \; (\itm{label}) \;\itm{info}\; ((\itm{label} \,\key{.}\, \Block)^{+}))\\
|
|
|
+x86_3 &::= & (\key{program} \;\itm{info} \;\Def^{*})
|
|
|
\end{array}
|
|
|
\]
|
|
|
\end{minipage}
|
|
@@ -6032,56 +6011,42 @@ x86_3 &::= & (\key{program} \;\itm{info} \;(\key{type}\;\itm{type})\;
|
|
|
\label{fig:x86-3}
|
|
|
\end{figure}
|
|
|
|
|
|
+An assignment of \code{fun-ref} becomes a \code{leaq} instruction
|
|
|
+as follows: \\
|
|
|
+\begin{tabular}{lll}
|
|
|
+\begin{minipage}{0.45\textwidth}
|
|
|
+\begin{lstlisting}
|
|
|
+ (assign |$\itm{lhs}$| (fun-ref |$f$|))
|
|
|
+\end{lstlisting}
|
|
|
+\end{minipage}
|
|
|
+&
|
|
|
+$\Rightarrow$
|
|
|
+&
|
|
|
+\begin{minipage}{0.4\textwidth}
|
|
|
+\begin{lstlisting}
|
|
|
+(leaq (fun-ref |$f$|) |$\itm{lhs}$|)
|
|
|
+\end{lstlisting}
|
|
|
+\end{minipage}
|
|
|
+\end{tabular} \\
|
|
|
|
|
|
|
|
|
+Regarding function definitions, we need to remove their parameters and
|
|
|
+instead perform parameter passing in terms of the conventions
|
|
|
+discussed in Section~\ref{sec:fun-x86}. That is, the arguments will be
|
|
|
+in the argument passing registers, and inside the function we should
|
|
|
+generate a \code{movq} instruction for each parameter, to move the
|
|
|
+argument value from the appropriate register to a new local variable
|
|
|
+with the same name as the old parameter.
|
|
|
|
|
|
-Next we consider compiling function definitions. The \code{flatten}
|
|
|
-pass should handle function definitions a lot like a \code{program}
|
|
|
-node; after all, the \code{program} node represents the \code{main}
|
|
|
-function. So the \code{flatten} pass, in addition to flattening the
|
|
|
-body of the function into a sequence of statements, should record the
|
|
|
-local variables in the $\Var^{*}$ field as shown below.
|
|
|
-\begin{lstlisting}
|
|
|
- (define (|$f$| [|\itm{xs}| : |\itm{ts}|]|$^{*}$|) : |\itm{rt}| (|$\Var^{*}$|) |$\Stmt^{+}$|)
|
|
|
-\end{lstlisting}
|
|
|
-In the \code{select-instructions} pass, we need to encode the
|
|
|
-parameter passing in terms of the conventions discussed in
|
|
|
-Section~\ref{sec:fun-x86}: a \code{movq} instruction for each
|
|
|
-parameter should be generated, to move the parameter value from the
|
|
|
-appropriate register to the appropriate variable from \itm{xs}.
|
|
|
-%% I recommend generating \code{movq} instructions to
|
|
|
-%% move the parameters from their registers and stack locations into the
|
|
|
-%% variables \itm{xs}, then let register allocation handle the assignment
|
|
|
-%% of those variables to homes.
|
|
|
-%% After this pass, the \itm{xs} can be
|
|
|
-%% added to the list of local variables. As mentioned in
|
|
|
-%% Section~\ref{sec:fun-x86}, we need to find out how far to move the
|
|
|
-%% stack pointer to ensure we have enough space for stack arguments in
|
|
|
-%% all the calls inside the body of this function. This pass is a good
|
|
|
-%% place to do this and store the result in the \itm{maxStack} field of
|
|
|
-%% the output \code{define} shown below.
|
|
|
-%% \begin{lstlisting}
|
|
|
-%% (define (|$f$|) |\itm{numParams}| (|$\Var^{*}$| |\itm{maxStack}|) |$\Instr^{+}$|)
|
|
|
-%% \end{lstlisting}
|
|
|
-
|
|
|
-Next, consider the compilation of non-tail function applications, which have
|
|
|
-the following form at the start of \code{select-instructions}.
|
|
|
+Next, consider the compilation of function calls, which have the
|
|
|
+following form upon input to \code{select-instructions}.
|
|
|
\begin{lstlisting}
|
|
|
(assign |\itm{lhs}| (call |\itm{fun}| |\itm{args}| |$\ldots$|))
|
|
|
\end{lstlisting}
|
|
|
In the mirror image of handling the parameters of function
|
|
|
-definitions, the arguments \itm{args} need to be moved to the
|
|
|
-argument passing registers, as discussed in
|
|
|
-Section~\ref{sec:fun-x86}.
|
|
|
-%% and the rest should be moved to the
|
|
|
-%% appropriate stack locations,
|
|
|
-%% You might want to introduce a new kind of AST node for stack
|
|
|
-%% arguments, \code{(stack-arg $i$)} where $i$ is the index of this
|
|
|
-%% argument with respect to the other stack arguments.
|
|
|
-%% As you're generating the code for parameter passing, take note of how
|
|
|
-%% many stack arguments are needed for purposes of computing the
|
|
|
-%% \itm{maxStack} discussed above.
|
|
|
-
|
|
|
+definitions, the arguments \itm{args} need to be moved to the argument
|
|
|
+passing registers.
|
|
|
+%
|
|
|
Once the instructions for parameter passing have been generated, the
|
|
|
function call itself can be performed with an indirect function call,
|
|
|
for which I recommend creating the new instruction
|
|
@@ -6092,57 +6057,77 @@ is stored in \code{rax}, so it needs to be moved into the \itm{lhs}.
|
|
|
(movq (reg rax) |\itm{lhs}|)
|
|
|
\end{lstlisting}
|
|
|
|
|
|
-Handling function applications in tail positions is only slightly
|
|
|
-different. The parameter passing is the same as non-tail calls,
|
|
|
-but the tail call itself cannot use the \code{indirect-callq} form.
|
|
|
-Generating, instead, an \code{indirect-jmp} form in \code{select-instructions}
|
|
|
-accounts for the fact that we intend to eventually use a \code{jmp}
|
|
|
-rather than a \code{callq} for the tail call. Of course, the
|
|
|
-\code{movq} from \code{rax} is not necessary after a tail call.
|
|
|
-
|
|
|
-
|
|
|
-The rest of the passes need only minor modifications to handle the new
|
|
|
-kinds of AST nodes: \code{function-ref}, \code{indirect-callq}, and
|
|
|
-\code{leaq}. Inside \code{uncover-live}, when computing the $W$ set
|
|
|
-(written variables) for an \code{indirect-callq} instruction, I
|
|
|
-recommend including all the caller-saved registers, which will have
|
|
|
-the affect of making sure that no caller-saved register actually needs
|
|
|
-to be saved. In \code{patch-instructions}, you should deal with the
|
|
|
-x86 idiosyncrasy that the destination argument of \code{leaq} must be
|
|
|
-a register. Additionally, \code{patch-instructions} should ensure that
|
|
|
-the \code{indirect-jmp} argument is \itm{rax}, our reserved
|
|
|
-register---this is to make code generation more convenient, because
|
|
|
-we will be trampling many registers before the tail call (as explained
|
|
|
+Regarding tail calls, the parameter passing is the same as non-tail
|
|
|
+calls: generate instructions to move the arguments into to the
|
|
|
+argument passing registers. After that we need to pop the frame from
|
|
|
+the procedure call stack. However, we do not yet know how big the
|
|
|
+frame is; that gets determined during register allocation. So instead
|
|
|
+of generating those instructions here, we make up a new instruction
|
|
|
+that means ``pop the frame and then indirect jump'', which we name
|
|
|
+\code{tail-jmp}.
|
|
|
+
|
|
|
+\section{Uncover Live}
|
|
|
+
|
|
|
+%% The rest of the passes need only minor modifications to handle the new
|
|
|
+%% kinds of AST nodes: \code{fun-ref}, \code{indirect-callq}, and
|
|
|
+%% \code{leaq}.
|
|
|
+
|
|
|
+Inside \code{uncover-live}, when computing the $W$ set (written
|
|
|
+variables) for an \code{indirect-callq} instruction, we recommend
|
|
|
+including all the caller-saved registers, which will have the affect
|
|
|
+of making sure that no caller-saved register actually needs to be
|
|
|
+saved.
|
|
|
+
|
|
|
+Recall that in Section~\ref{sec:reg-alloc-gc} we discussed the need to
|
|
|
+spill vector-typed variables that are live during a call to the
|
|
|
+collector. With the addition of functions to our language, we need to
|
|
|
+revisit this issue. Many functions will perform allocation and
|
|
|
+therefore have calls to the collector inside of them. Thus, we should
|
|
|
+not only spill a vector-type variable when it is live during a call to
|
|
|
+\code{collect}, but we shold spill the variable if it is live during
|
|
|
+any function call.
|
|
|
+
|
|
|
+\section{Patch Instructions}
|
|
|
+
|
|
|
+In \code{patch-instructions}, you should deal with the x86
|
|
|
+idiosyncrasy that the destination argument of \code{leaq} must be a
|
|
|
+register. Additionally, \code{patch-instructions} should ensure that
|
|
|
+the argument of \code{tail-jmp} is \itm{rax}, our reserved
|
|
|
+register---this is to make code generation more convenient, because we
|
|
|
+will be trampling many registers before the tail call (as explained
|
|
|
below).
|
|
|
|
|
|
+\section{Print x86}
|
|
|
+
|
|
|
+
|
|
|
For the \code{print-x86} pass, we recommend the following translations:
|
|
|
\begin{lstlisting}
|
|
|
- (function-ref |\itm{label}|) |$\Rightarrow$| |\itm{label}|(%rip)
|
|
|
+ (fun-ref |\itm{label}|) |$\Rightarrow$| |\itm{label}|(%rip)
|
|
|
(indirect-callq |\itm{arg}|) |$\Rightarrow$| callq *|\itm{arg}|
|
|
|
\end{lstlisting}
|
|
|
-Handling \code{indirect-jmp} requires a bit more care. A
|
|
|
-straightforward translation of \code{indirect-jmp} would be \code{jmp
|
|
|
+Handling \code{tail-jmp} requires a bit more care. A
|
|
|
+straightforward translation of \code{tail-jmp} would be \code{jmp
|
|
|
*$\itm{arg}$}, which is what we will want to do, but \emph{before}
|
|
|
this jump we need to pop the saved registers and reset the frame
|
|
|
pointer. Basically, we want to restore the state of the registers to
|
|
|
the point they were at when the current function was called, since we
|
|
|
are about to jump to the beginning of a \emph{new} function.
|
|
|
|
|
|
-This is why it was convenient to ensure the \code{jmp} argument was
|
|
|
-\itm{rax}. A sufficiently clever compiler could determine that a
|
|
|
-function body always ends in a tail call, and thus avoid generating
|
|
|
-code to restore registers and return via \code{ret}, but for
|
|
|
-simplicity we do not need to do this.
|
|
|
+%% This is why it was convenient to ensure the \code{jmp} argument was
|
|
|
+%% \itm{rax}. A sufficiently clever compiler could determine that a
|
|
|
+%% function body always ends in a tail call, and thus avoid generating
|
|
|
+%% code to restore registers and return via \code{ret}, but for
|
|
|
+%% simplicity we do not need to do this.
|
|
|
|
|
|
-\margincomment{\footnotesize The reason we can't easily optimize
|
|
|
- this is because the details of function prologue and epilogue
|
|
|
- are not exposed in the AST, and just emitted as strings in
|
|
|
- \code{print-x86}.}
|
|
|
+%% \margincomment{\footnotesize The reason we can't easily optimize
|
|
|
+%% this is because the details of function prologue and epilogue
|
|
|
+%% are not exposed in the AST, and just emitted as strings in
|
|
|
+%% \code{print-x86}.}
|
|
|
|
|
|
-As this implies, your \code{print-x86} pass needs to add
|
|
|
-the code for saving and restoring callee-saved registers, if
|
|
|
-you have not already implemented that. This is necessary when
|
|
|
-generating code for function definitions.
|
|
|
+Note that your \code{print-x86} pass needs to add the code for saving
|
|
|
+and restoring callee-saved registers, if you have not already
|
|
|
+implemented that. This is necessary when generating code for function
|
|
|
+definitions.
|
|
|
|
|
|
%% For function definitions, the \code{print-x86} pass should add the
|
|
|
%% code for saving and restoring the callee-saved registers, if you
|
|
@@ -6151,14 +6136,16 @@ generating code for function definitions.
|
|
|
\section{An Example Translation}
|
|
|
|
|
|
Figure~\ref{fig:add-fun} shows an example translation of a simple
|
|
|
-function in $R_4$ to x86. The figure includes the results of the
|
|
|
-\code{flatten} and \code{select-instructions} passes. Can you see any
|
|
|
-ways to improve the translation?
|
|
|
+function in $R_4$ to x86. The figure also includes the results of the
|
|
|
+\code{explicate-control} and \code{select-instructions} passes. We
|
|
|
+have ommited the \code{has-type} AST nodes for readability. Can you
|
|
|
+see any ways to improve the translation?
|
|
|
|
|
|
\begin{figure}[tbp]
|
|
|
-\begin{tabular}{lll}
|
|
|
-\begin{minipage}{0.5\textwidth}
|
|
|
-\begin{lstlisting}
|
|
|
+\begin{tabular}{ll}
|
|
|
+\begin{minipage}{0.45\textwidth}
|
|
|
+% s3_2.rkt
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
(program
|
|
|
(define (add [x : Integer]
|
|
|
[y : Integer])
|
|
@@ -6166,103 +6153,120 @@ ways to improve the translation?
|
|
|
(add 40 2))
|
|
|
\end{lstlisting}
|
|
|
$\Downarrow$
|
|
|
-\begin{lstlisting}
|
|
|
-(program (t.1 t.2)
|
|
|
- (defines
|
|
|
- (define (add.1 [x.1 : Integer]
|
|
|
- [y.1 : Integer])
|
|
|
- : Integer (t.3)
|
|
|
- (assign t.3 (+ x.1 y.1))
|
|
|
- (return t.3)))
|
|
|
- (assign t.1 (function-ref add.1))
|
|
|
- (assign t.2 (app t.1 40 2))
|
|
|
- (return t.2))
|
|
|
-\end{lstlisting}
|
|
|
-$\Downarrow$
|
|
|
-\begin{lstlisting}
|
|
|
-(program ((rs.1 t.1 t.2) 0)
|
|
|
- (type Integer)
|
|
|
- (defines
|
|
|
- (define (add28545) 3
|
|
|
- ((rs.2 x.2 y.3 t.4) 0)
|
|
|
- (movq (reg rdi) (var rs.2))
|
|
|
- (movq (reg rsi) (var x.2))
|
|
|
- (movq (reg rdx) (var y.3))
|
|
|
- (movq (var x.2) (var t.4))
|
|
|
- (addq (var y.3) (var t.4))
|
|
|
- (movq (var t.4) (reg rax))))
|
|
|
- (movq (int 16384) (reg rdi))
|
|
|
- (movq (int 16) (reg rsi))
|
|
|
- (callq initialize)
|
|
|
- (movq (global-value rootstack_begin)
|
|
|
- (var rs.1))
|
|
|
- (leaq (function-ref add28545) (var t.1))
|
|
|
- (movq (var rs.1) (reg rdi))
|
|
|
- (movq (int 40) (reg rsi))
|
|
|
- (movq (int 2) (reg rdx))
|
|
|
- (indirect-callq (var t.1))
|
|
|
- (movq (reg rax) (var t.2))
|
|
|
- (movq (var t.2) (reg rax)))
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+(program ()
|
|
|
+ (define (add86 [x87 : Integer]
|
|
|
+ [y88 : Integer]) : Integer ()
|
|
|
+ ((add86start . (return (+ x87 y88)))))
|
|
|
+ (define (main) : Integer ()
|
|
|
+ ((mainstart .
|
|
|
+ (seq (assign tmp89 (fun-ref add86))
|
|
|
+ (tailcall tmp89 40 2))))))
|
|
|
\end{lstlisting}
|
|
|
\end{minipage}
|
|
|
&
|
|
|
-\begin{minipage}{0.4\textwidth}
|
|
|
+$\Rightarrow$
|
|
|
+\begin{minipage}{0.5\textwidth}
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+(program ()
|
|
|
+ (define (add86)
|
|
|
+ ((locals (x87 . Integer) (y88 . Integer))
|
|
|
+ (num-params . 2))
|
|
|
+ ((add86start .
|
|
|
+ (block ()
|
|
|
+ (movq (reg rcx) (var x87))
|
|
|
+ (movq (reg rdx) (var y88))
|
|
|
+ (movq (var x87) (reg rax))
|
|
|
+ (addq (var y88) (reg rax))
|
|
|
+ (jmp add86conclusion)))))
|
|
|
+ (define (main)
|
|
|
+ ((locals . ((tmp89 . (Integer Integer -> Integer))))
|
|
|
+ (num-params . 0))
|
|
|
+ ((mainstart .
|
|
|
+ (block ()
|
|
|
+ (leaq (fun-ref add86) (var tmp89))
|
|
|
+ (movq (int 40) (reg rcx))
|
|
|
+ (movq (int 2) (reg rdx))
|
|
|
+ (tail-jmp (var tmp89))))))
|
|
|
+\end{lstlisting}
|
|
|
$\Downarrow$
|
|
|
+\end{minipage}
|
|
|
+\end{tabular}
|
|
|
+\begin{tabular}{lll}
|
|
|
+\begin{minipage}{0.3\textwidth}
|
|
|
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
- .globl add28545
|
|
|
-add28545:
|
|
|
+_add90start:
|
|
|
+ movq %rcx, %rsi
|
|
|
+ movq %rdx, %rcx
|
|
|
+ movq %rsi, %rax
|
|
|
+ addq %rcx, %rax
|
|
|
+ jmp _add90conclusion
|
|
|
+ .globl _add90
|
|
|
+ .align 16
|
|
|
+_add90:
|
|
|
pushq %rbp
|
|
|
movq %rsp, %rbp
|
|
|
- pushq %r15
|
|
|
- pushq %r14
|
|
|
- pushq %r13
|
|
|
pushq %r12
|
|
|
pushq %rbx
|
|
|
- subq $8, %rsp
|
|
|
- movq %rdi, %rbx
|
|
|
- movq %rsi, %rbx
|
|
|
- movq %rdx, %rcx
|
|
|
- addq %rcx, %rbx
|
|
|
- movq %rbx, %rax
|
|
|
- addq $8, %rsp
|
|
|
+ pushq %r13
|
|
|
+ pushq %r14
|
|
|
+ subq $0, %rsp
|
|
|
+ jmp _add90start
|
|
|
+_add90conclusion:
|
|
|
+ addq $0, %rsp
|
|
|
+ popq %r14
|
|
|
+ popq %r13
|
|
|
popq %rbx
|
|
|
popq %r12
|
|
|
- popq %r13
|
|
|
- popq %r14
|
|
|
- popq %r15
|
|
|
+ subq $0, %r15
|
|
|
popq %rbp
|
|
|
retq
|
|
|
+\end{lstlisting}
|
|
|
+\end{minipage}
|
|
|
+&
|
|
|
+\begin{minipage}{0.3\textwidth}
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+_mainstart:
|
|
|
+ leaq _add90(%rip), %rsi
|
|
|
+ movq $40, %rcx
|
|
|
+ movq $2, %rdx
|
|
|
+ movq %rsi, %rax
|
|
|
+ addq $0, %rsp
|
|
|
+ popq %r14
|
|
|
+ popq %r13
|
|
|
+ popq %rbx
|
|
|
+ popq %r12
|
|
|
+ subq $0, %r15
|
|
|
+ popq %rbp
|
|
|
+ jmp *%rax
|
|
|
|
|
|
.globl _main
|
|
|
+ .align 16
|
|
|
_main:
|
|
|
pushq %rbp
|
|
|
movq %rsp, %rbp
|
|
|
- pushq %r15
|
|
|
- pushq %r14
|
|
|
- pushq %r13
|
|
|
pushq %r12
|
|
|
pushq %rbx
|
|
|
- subq $8, %rsp
|
|
|
- movq $16384, %rdi
|
|
|
- movq $16, %rsi
|
|
|
- callq _initialize
|
|
|
- movq _rootstack_begin(%rip), %rcx
|
|
|
- leaq add28545(%rip), %rbx
|
|
|
- movq %rcx, %rdi
|
|
|
- movq $40, %rsi
|
|
|
- movq $2, %rdx
|
|
|
- callq *%rbx
|
|
|
- movq %rax, %rbx
|
|
|
- movq %rbx, %rax
|
|
|
- movq %rax, %rdi
|
|
|
- callq _print_int
|
|
|
- movq $0, %rax
|
|
|
- addq $8, %rsp
|
|
|
+ pushq %r13
|
|
|
+ pushq %r14
|
|
|
+ subq $0, %rsp
|
|
|
+ movq $16384, %rdi
|
|
|
+ movq $16, %rsi
|
|
|
+ callq _initialize
|
|
|
+ movq _rootstack_begin(%rip), %r15
|
|
|
+ jmp _mainstart
|
|
|
+\end{lstlisting}
|
|
|
+\end{minipage}
|
|
|
+&
|
|
|
+\begin{minipage}{0.3\textwidth}
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+_mainconclusion:
|
|
|
+ addq $0, %rsp
|
|
|
+ popq %r14
|
|
|
+ popq %r13
|
|
|
popq %rbx
|
|
|
popq %r12
|
|
|
- popq %r13
|
|
|
- popq %r14
|
|
|
- popq %r15
|
|
|
+ subq $0, %r15
|
|
|
popq %rbp
|
|
|
retq
|
|
|
\end{lstlisting}
|
|
@@ -6313,7 +6317,8 @@ programs.
|
|
|
\path[->,bend left=15] (x86-4) edge [above] node {\ttfamily\footnotesize patch-instr.} (x86-5);
|
|
|
\path[->,bend right=15] (x86-5) edge [left] node {\ttfamily\footnotesize\color{red} print-x86} (x86-6);
|
|
|
\end{tikzpicture}
|
|
|
-\caption{Diagram of the passes for $R_4$, a language with functions.}
|
|
|
+\caption{Diagram of the passes for $R_4$, a language with functions.
|
|
|
+ UPDATE ME -Jeremy}
|
|
|
\label{fig:R4-passes}
|
|
|
\end{figure}
|
|
|
|
|
@@ -6610,7 +6615,7 @@ application, we turn function references into closures.
|
|
|
\begin{tabular}{lll}
|
|
|
\begin{minipage}{0.3\textwidth}
|
|
|
\begin{lstlisting}
|
|
|
-(function-ref |$f$|)
|
|
|
+(fun-ref |$f$|)
|
|
|
\end{lstlisting}
|
|
|
\end{minipage}
|
|
|
&
|
|
@@ -6618,7 +6623,7 @@ $\Rightarrow$
|
|
|
&
|
|
|
\begin{minipage}{0.5\textwidth}
|
|
|
\begin{lstlisting}
|
|
|
-(vector (function-ref |$f$|))
|
|
|
+(vector (fun-ref |$f$|))
|
|
|
\end{lstlisting}
|
|
|
\end{minipage}
|
|
|
\end{tabular} \\
|
|
@@ -6660,8 +6665,8 @@ $\Downarrow$
|
|
|
(let ((y 4))
|
|
|
(lambda: ((z : Integer)) : Integer
|
|
|
(+ x (+ y z)))))
|
|
|
- (let ((g (app (function-ref f) 5)))
|
|
|
- (let ((h (app (function-ref f) 3)))
|
|
|
+ (let ((g (app (fun-ref f) 5)))
|
|
|
+ (let ((h (app (fun-ref f) 3)))
|
|
|
(+ (app g 11) (app h 15)))))
|
|
|
\end{lstlisting}
|
|
|
$\Downarrow$
|
|
@@ -6669,14 +6674,14 @@ $\Downarrow$
|
|
|
(program (type Integer)
|
|
|
(define (f (clos.1 : _) (x : Integer)) : (Integer -> Integer)
|
|
|
(let ((y 4))
|
|
|
- (vector (function-ref lam.1) x y)))
|
|
|
+ (vector (fun-ref lam.1) x y)))
|
|
|
(define (lam.1 (clos.2 : _) (z : Integer)) : Integer
|
|
|
(let ((x (vector-ref clos.2 1)))
|
|
|
(let ((y (vector-ref clos.2 2)))
|
|
|
(+ x (+ y z)))))
|
|
|
- (let ((g (let ((t.1 (vector (function-ref f))))
|
|
|
+ (let ((g (let ((t.1 (vector (fun-ref f))))
|
|
|
(app (vector-ref t.1 0) t.1 5))))
|
|
|
- (let ((h (let ((t.2 (vector (function-ref f))))
|
|
|
+ (let ((h (let ((t.2 (vector (fun-ref f))))
|
|
|
(app (vector-ref t.2 0) t.2 3))))
|
|
|
(+ (let ((t.3 g)) (app (vector-ref t.3 0) t.3 11))
|
|
|
(let ((t.4 h)) (app (vector-ref t.4 0) t.4 15))))))
|