|
@@ -10502,10 +10502,11 @@ generate better code by taking this fact into account.
|
|
|
|
|
|
The output language of \code{explicate\_control} is \LangCLoop{}
|
|
|
(Figure~\ref{fig:c7-syntax}), which is nearly identical to
|
|
|
-\LangCLam{}. The only syntactic difference is that \code{Call} and
|
|
|
-\code{read} may also appear as statements. The most significant
|
|
|
-difference between \LangCLam{} and \LangCLoop{} is that the
|
|
|
-control-flow graphs of the later may contain cycles.
|
|
|
+\LangCIf{}. The only syntactic difference is that
|
|
|
+\code{read} may also appear as a statement. The most significant
|
|
|
+difference between programs in \LangCIf{} and programs in \LangCLoop{},
|
|
|
+generated by the passes of the compiler,
|
|
|
+is that the control-flow graphs of the later may contain cycles.
|
|
|
|
|
|
\begin{figure}[tp]
|
|
|
\fbox{
|
|
@@ -11941,8 +11942,11 @@ movq |$\itm{rhs}'$|, |$8(n+1)$|(%r11)
|
|
|
\fi}
|
|
|
\end{minipage}
|
|
|
\end{center}
|
|
|
-The $\itm{lhs}'$, $\itm{tup}'$, and $\itm{rhs}'$ are obtained by
|
|
|
-translating $\itm{tup}$ and $\itm{rhs}$ to x86. The move of $\itm{tup}'$ to
|
|
|
+\racket{The $\itm{lhs}'$, $\itm{tup}'$, and $\itm{rhs}'$}
|
|
|
+\python{The $\itm{tup}'$ and $\itm{rhs}'$}
|
|
|
+are obtained by translating from \LangCVec{} to x86.
|
|
|
+%
|
|
|
+The move of $\itm{tup}'$ to
|
|
|
register \code{r11} ensures that offset expression
|
|
|
\code{$-8(n+1)$(\%r11)} contains a register operand. This requires
|
|
|
removing \code{r11} from consideration by the register allocating.
|
|
@@ -11952,7 +11956,6 @@ Why not use \code{rax} instead of \code{r11}? Suppose we instead used
|
|
|
\begin{lstlisting}
|
|
|
movq |$\itm{tup}'$|, %rax
|
|
|
movq |$\itm{rhs}'$|, |$8(n+1)$|(%rax)
|
|
|
-movq $0, |$\itm{lhs}'$|
|
|
|
\end{lstlisting}
|
|
|
Next, suppose that $\itm{rhs}'$ ends up as a stack location, so
|
|
|
\code{patch\_instructions} would insert a move through \code{rax}
|
|
@@ -11961,7 +11964,6 @@ as follows.
|
|
|
movq |$\itm{tup}'$|, %rax
|
|
|
movq |$\itm{rhs}'$|, %rax
|
|
|
movq %rax, |$8(n+1)$|(%rax)
|
|
|
-movq $0, |$\itm{lhs}'$|
|
|
|
\end{lstlisting}
|
|
|
But the above sequence of instructions does not work because we're
|
|
|
trying to use \code{rax} for two different values ($\itm{tup}'$ and
|
|
@@ -12056,7 +12058,7 @@ available for use by the register allocator.
|
|
|
\begin{array}{lcl}
|
|
|
\Arg &::=& \gray{ \key{\$}\Int \MID \key{\%}\Reg \MID \Int\key{(}\key{\%}\Reg\key{)} \MID \key{\%}\itm{bytereg} } \MID \Var \key{(\%rip)} \\
|
|
|
\LangXGlobalM{} &::= & \gray{ \key{.globl main} }\\
|
|
|
- & & \gray{ \key{main:} \; \Instr\ldots }
|
|
|
+ & & \gray{ \key{main:} \; \Instr^{*} }
|
|
|
\end{array}
|
|
|
\]
|
|
|
\end{minipage}
|
|
@@ -12930,10 +12932,11 @@ present these findings.
|
|
|
\label{ch:Lfun}
|
|
|
\index{subject}{function}
|
|
|
|
|
|
-This chapter studies the compilation of functions similar to those
|
|
|
-found in the C language. This corresponds to a subset of \racket{Typed
|
|
|
- Racket} \python{Python} in which only top-level function definitions
|
|
|
-are allowed. This kind of function is an important stepping stone to
|
|
|
+This chapter studies the compilation of a subset of \racket{Typed
|
|
|
+ Racket}\python{Python} in which only top-level function definitions
|
|
|
+are allowed..
|
|
|
+This kind of function is a realistic example as the C language imposes
|
|
|
+similar restrictions. It is also an important stepping stone to
|
|
|
implementing lexically-scoped functions in the form of \key{lambda}
|
|
|
abstractions, which is the topic of Chapter~\ref{ch:Llambda}.
|
|
|
|
|
@@ -12949,11 +12952,11 @@ definitions does not matter).
|
|
|
%
|
|
|
\python{The abstract syntax for function parameters in
|
|
|
Figure~\ref{fig:Rfun-syntax} is a list of pairs, where each pair
|
|
|
- consists of a parameter name and its type. This differs from
|
|
|
- Python's \code{ast} module, which has a more complex syntax for
|
|
|
- function parameters, for example, to handle keyword parameters and
|
|
|
- defaults. The type checker in \code{type\_check\_Lfun} converts the
|
|
|
- more commplex syntax into the simpler syntax of
|
|
|
+ consists of a parameter name and its type. This design differs from
|
|
|
+ Python's \code{ast} module, which has a more complex structure for
|
|
|
+ function parameters to handle keyword parameters,
|
|
|
+ defaults, and so on. The type checker in \code{type\_check\_Lfun} converts the
|
|
|
+ complex Python abstract syntax into the simpler syntax of
|
|
|
Figure~\ref{fig:Rfun-syntax}. The fourth and sixth parameters of the
|
|
|
\code{FunctionDef} constructor are for decorators and a type
|
|
|
comment, neither of which are used by our compiler. We recommend
|
|
@@ -12961,10 +12964,13 @@ definitions does not matter).
|
|
|
}
|
|
|
%
|
|
|
The concrete syntax for function application\index{subject}{function
|
|
|
- application} is $\CAPPLY{\Exp}{\Exp \ldots}$ where the first expression
|
|
|
-must evaluate to a function and the rest are the arguments. The
|
|
|
+ application} is
|
|
|
+\python{$\CAPPLY{\Exp}{\Exp\code{,} \ldots}$}
|
|
|
+\racket{$\CAPPLY{\Exp}{\Exp \ldots}$}
|
|
|
+ where the first expression
|
|
|
+must evaluate to a function and the remaining expressions are the arguments. The
|
|
|
abstract syntax for function application is
|
|
|
-$\APPLY{\Exp}{\Exp\ldots}$.
|
|
|
+$\APPLY{\Exp}{\Exp^*}$.
|
|
|
|
|
|
%% The syntax for function application does not include an explicit
|
|
|
%% keyword, which is error prone when using \code{match}. To alleviate
|
|
@@ -12992,7 +12998,7 @@ limitation of these functions (with respect to
|
|
|
\racket{Racket}\python{Python} functions) is that they are not
|
|
|
lexically scoped. That is, the only external entities that can be
|
|
|
referenced from inside a function body are other globally-defined
|
|
|
-functions. The syntax of \LangFun{} prevents functions from being
|
|
|
+functions. The syntax of \LangFun{} prevents function definitions from being
|
|
|
nested inside each other.
|
|
|
|
|
|
\newcommand{\LfunGrammarRacket}{
|
|
@@ -13023,7 +13029,9 @@ nested inside each other.
|
|
|
\Type &::=& \key{FunctionType}\LP \Type^{*} \key{, } \Type \RP \\
|
|
|
\Exp &::=& \CALL{\Exp}{\Exp^{*}}\\
|
|
|
\Stmt &::=& \RETURN{\Exp} \\
|
|
|
- \Params &::=& \LS\LP\Var\key{,}\Type\RP\code{,}\ldots\RS \\
|
|
|
+ \Params &::=& \LP\Var\key{,}\Type\RP^*
|
|
|
+ % was: \LS\LP\Var\key{,}\Type\RP\code{,}\ldots\RS
|
|
|
+ \\
|
|
|
\Def &::=& \FUNDEF{\Var}{\Params}{\Type}{}{\Stmt^{+}}
|
|
|
\end{array}
|
|
|
}
|
|
@@ -13292,7 +13300,7 @@ interpreter, the case for the
|
|
|
AST is responsible for setting up the mutual recursion between the
|
|
|
top-level function definitions. We begin by create a mapping
|
|
|
\code{env} from every function name to its type. We then type check
|
|
|
-the program using this \code{env}.
|
|
|
+the program using this mapping.
|
|
|
%
|
|
|
In the case for function \racket{application}\python{call}, we match
|
|
|
the type of the function expression to a function type and check that
|
|
@@ -13427,8 +13435,8 @@ class TypeCheckLfun(TypeCheckLtup):
|
|
|
%% stack and what callq and retq does.\\ --Jeremy }
|
|
|
|
|
|
The x86 architecture provides a few features to support the
|
|
|
-implementation of functions. We have already seen that x86 provides
|
|
|
-labels so that one can refer to the location of an instruction, as is
|
|
|
+implementation of functions. We have already seen that there are
|
|
|
+labels in x86 so that one can refer to the location of an instruction, as is
|
|
|
needed for jump instructions. Labels can also be used to mark the
|
|
|
beginning of the instructions for a function. Going further, we can
|
|
|
obtain the address of a label by using the \key{leaq} instruction and
|
|
@@ -13439,7 +13447,7 @@ address of the \code{inc} label into the \code{rbx} register.
|
|
|
\end{lstlisting}
|
|
|
The instruction pointer register \key{rip} (aka. the program counter
|
|
|
\index{subject}{program counter}) always points to the next
|
|
|
-instruction to be executed. When combined with an label, as in
|
|
|
+instruction to be executed. When combined with a label, as in
|
|
|
\code{inc(\%rip)}, the assembler computes the distance $d$ between the
|
|
|
address of \code{inc} and where the \code{rip} would be at that moment
|
|
|
and then changes the \code{inc(\%rip)} argument to \code{$d$(\%rip)},
|
|
@@ -13499,7 +13507,8 @@ is, anything that is at or above the stack pointer. The callee is free
|
|
|
to use locations that are below the stack pointer.
|
|
|
|
|
|
Recall that we are storing variables of tuple type on the root stack.
|
|
|
-So the prelude needs to move the root stack pointer \code{r15} up and
|
|
|
+So the prelude needs to move the root stack pointer \code{r15} up
|
|
|
+according to the number of variables of tuple type and
|
|
|
the conclusion needs to move the root stack pointer back down. Also,
|
|
|
the prelude must initialize to \code{0} this frame's slots in the root
|
|
|
stack to signal to the garbage collector that those slots do not yet
|
|
@@ -13512,15 +13521,15 @@ recall from Section~\ref{sec:calling-conventions} that the registers
|
|
|
are divided into two groups, the caller-saved registers and the
|
|
|
callee-saved registers. The caller should assume that all the
|
|
|
caller-saved registers get overwritten with arbitrary values by the
|
|
|
-callee. That is why we recommend in
|
|
|
+callee. For that reason we recommend in
|
|
|
Section~\ref{sec:calling-conventions} that variables that are live
|
|
|
during a function call should not be assigned to caller-saved
|
|
|
registers.
|
|
|
|
|
|
On the flip side, if the callee wants to use a callee-saved register,
|
|
|
the callee must save the contents of those registers on their stack
|
|
|
-frame and then put them back prior to returning to the caller. That
|
|
|
-is why we recommended in Section~\ref{sec:calling-conventions} that if
|
|
|
+frame and then put them back prior to returning to the caller. For
|
|
|
+that reason we recommend in Section~\ref{sec:calling-conventions} that if
|
|
|
the register allocator assigns a variable to a callee-saved register,
|
|
|
then the prelude of the \code{main} function must save that register
|
|
|
to the stack and the conclusion of \code{main} must restore it. This
|
|
@@ -13600,12 +13609,12 @@ In general, the amount of stack space used by a program is determined
|
|
|
by the longest chain of nested function calls. That is, if function
|
|
|
$f_1$ calls $f_2$, $f_2$ calls $f_3$, $\ldots$, $f_n$, then the amount
|
|
|
of stack space is linear in $n$. The depth $n$ can grow quite large
|
|
|
-in the case of recursive or mutually recursive functions. However, in
|
|
|
+if functions are (mutually) recursive. However, in
|
|
|
some cases we can arrange to use only a constant amount of space for a
|
|
|
long chain of nested function calls.
|
|
|
|
|
|
-If a function call is the last action in a function body, then that
|
|
|
-call is said to be a \emph{tail call}\index{subject}{tail call}.
|
|
|
+A \emph{tail call}\index{subject}{tail call} is a function call that
|
|
|
+happens as the last action in a function body.
|
|
|
For example, in the following
|
|
|
program, the recursive call to \code{tail\_sum} is a tail call.
|
|
|
\begin{center}
|
|
@@ -13633,10 +13642,10 @@ print( tail_sum(3, 0) + 36)
|
|
|
\end{center}
|
|
|
At a tail call, the frame of the caller is no longer needed, so we can
|
|
|
pop the caller's frame before making the tail call. With this
|
|
|
-approach, a recursive function that only makes tail calls will only
|
|
|
-use a constant amount of stack space. Functional languages like
|
|
|
-Racket typically rely heavily on recursive functions, so they
|
|
|
-typically guarantee that all tail calls will be optimized in this way.
|
|
|
+approach, a recursive function that only makes tail calls ends up
|
|
|
+using a constant amount of stack space. Functional languages like
|
|
|
+Racket rely heavily on recursive functions, so the definition of
|
|
|
+Racket \emph{requires} that all tail calls be optimized in this way.
|
|
|
\index{subject}{frame}
|
|
|
|
|
|
Some care is needed with regards to argument passing in tail calls.
|
|
@@ -13680,7 +13689,8 @@ just about everything else.
|
|
|
\label{sec:shrink-r4}
|
|
|
|
|
|
The \code{shrink} pass performs a minor modification to ease the
|
|
|
-later passes. This pass introduces an explicit \code{main} function.
|
|
|
+later passes. This pass introduces an explicit \code{main} function
|
|
|
+that gobbles up all the top-level statements of the module.
|
|
|
%
|
|
|
\racket{It also changes the top \code{ProgramDefsExp} form to
|
|
|
\code{ProgramDefs}.}
|
|
@@ -13702,7 +13712,7 @@ Module(|$\Def\ldots\Stmt\ldots$|)
|
|
|
\end{lstlisting}
|
|
|
where $\itm{mainDef}$ is
|
|
|
\begin{lstlisting}
|
|
|
-FunctionDef('main', [], int, None, |$\Stmt'\ldots$|Return(Constant(0)), None)
|
|
|
+FunctionDef('main', [], int, None, |$\Stmt\ldots$|Return(Constant(0)), None)
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
|
|
@@ -13776,7 +13786,7 @@ than six arguments to pass the first five arguments as usual, but it
|
|
|
packs the rest of the arguments into a vector and passes it as the
|
|
|
sixth argument.
|
|
|
|
|
|
-Each function definition with too many parameters is transformed as
|
|
|
+Each function definition with seven or more parameters is transformed as
|
|
|
follows.
|
|
|
{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
@@ -13805,7 +13815,7 @@ the $k$th element of the tuple, where $k = i - 6$.
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
|
\begin{lstlisting}
|
|
|
- Name(|$x_i$|) |$\Rightarrow$| Subscript(tup, Constant(|$k$|))
|
|
|
+ Name(|$x_i$|) |$\Rightarrow$| Subscript(tup, Constant(|$k$|), Load())
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
|
|
@@ -13916,7 +13926,7 @@ be updated with cases for
|
|
|
\racket{\code{Apply}}\python{\code{Call}} and \code{FunRef} and the
|
|
|
function for predicate context should be updated for
|
|
|
\racket{\code{Apply}}\python{\code{Call}} but not \code{FunRef}. (A
|
|
|
-\code{FunRef} can't be a Boolean.) In assignment and predicate
|
|
|
+\code{FunRef} cannot be a Boolean.) In assignment and predicate
|
|
|
contexts, \code{Apply} becomes \code{Call}\racket{, whereas in tail position
|
|
|
\code{Apply} becomes \code{TailCall}}. We recommend defining a new
|
|
|
auxiliary function for processing function definitions. This code is
|
|
@@ -13954,8 +13964,8 @@ appropriate explicate functions for the various contexts.
|
|
|
\Exp &::= & \FUNREF{\itm{label}} \MID \CALL{\Atm}{\Atm^{*}} \\
|
|
|
\Stmt &::= & \TAILCALL{\Atm}{\Atm^{*}} \\
|
|
|
\Params &::=& \LS\LP\Var\key{,}\Type\RP\code{,}\ldots\RS \\
|
|
|
-\Block &::=& \Stmt^{*} \\
|
|
|
-\Blocks &::=& \LC\itm{label}\key{:}\Block\code{,}\ldots\RC \\
|
|
|
+\Block &::=& \itm{label}\key{:} \Stmt^{*} \\
|
|
|
+\Blocks &::=& \LC\Block\code{,}\ldots\RC \\
|
|
|
\Def &::=& \DEF{\itm{label}}{\Params}{\Blocks}{\key{None}}{\Type}{\key{None}}
|
|
|
\end{array}
|
|
|
}
|
|
@@ -14012,13 +14022,12 @@ language, whose syntax is defined in Figure~\ref{fig:x86-3}.
|
|
|
\[
|
|
|
\begin{array}{lcl}
|
|
|
\Arg &::=& \gray{ \key{\$}\Int \MID \key{\%}\Reg \MID \Int\key{(}\key{\%}\Reg\key{)} \MID \key{\%}\itm{bytereg} } \MID \Var \key{(\%rip)} \\
|
|
|
-\itm{cc} & ::= & \gray{ \key{e} \MID \key{l} \MID \key{le} \MID \key{g} \MID \key{ge} } \\
|
|
|
+\itm{cc} & ::= & \gray{ \key{e} \MID \key{ne} \MID \key{l} \MID \key{le} \MID \key{g} \MID \key{ge} } \\
|
|
|
\Instr &::=& \ldots
|
|
|
\MID \key{callq}\;\key{*}\Arg \MID \key{tailjmp}\;\Arg
|
|
|
\MID \key{leaq}\;\Arg\key{,}\;\key{\%}\Reg \\
|
|
|
-\Block &::= & \Instr^{*} \\
|
|
|
-\Blocks &::=& \LP\LP\itm{label} \,\key{.}\, \Block\RP\ldots\RP\\
|
|
|
-\Def &::= & \LP\key{define} \; \LP\itm{label} \RP \; \Blocks \RP\\
|
|
|
+\Block &::= & \itm{label}\key{:}\, \Instr^{*} \\
|
|
|
+\Def &::= & \key{.globl}\,\itm{label}\; \Block^{*} \\
|
|
|
\LangXIndCallM{} &::= & \Def\ldots
|
|
|
\end{array}
|
|
|
\]
|
|
@@ -14055,8 +14064,10 @@ language, whose syntax is defined in Figure~\ref{fig:x86-3}.
|
|
|
&\MID& \gray{ \GLOBAL{\Var} } \MID \FUNREF{\itm{label}} \\
|
|
|
\Instr &::=& \ldots \MID \INDCALLQ{\Arg}{\itm{int}}
|
|
|
\MID \TAILJMP{\Arg}{\itm{int}}\\
|
|
|
- &\MID& \BININSTR{\code{leaq}}{\Arg}{\REG{\Reg}}\\
|
|
|
- \Def &::= & \DEF{\itm{label}}{\LS\RS}{\LC\itm{label}\key{:}\,\Instr^{*}\code{,}\ldots\RC}{\_}{\Type}{\_} \\
|
|
|
+ &\MID& \BININSTR{\scode{leaq}}{\Arg}{\REG{\Reg}}\\
|
|
|
+ \Block &::=&\itm{label}\key{:}\,\Instr^{*} \\
|
|
|
+ \Blocks &::= & \LC\Block\code{,}\ldots\RC\\
|
|
|
+ \Def &::= & \DEF{\itm{label}}{\LS\RS}{\Blocks}{\_}{\Type}{\_} \\
|
|
|
\LangXIndCallM{} &::= & \XPROGRAMDEFS{\LS\Def\code{,}\ldots\RS}
|
|
|
\end{array}
|
|
|
\]
|
|
@@ -14075,17 +14086,31 @@ is the translation of $\itm{lhs}$ from \Atm{} in \LangCFun{}
|
|
|
to \Arg{} in \LangXIndCallVar{}. \\
|
|
|
\begin{tabular}{lcl}
|
|
|
\begin{minipage}{0.35\textwidth}
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
|$\itm{lhs}$| = (fun-ref |$f$|);
|
|
|
\end{lstlisting}
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+ |$\itm{lhs}$| = FunRef(|$f$|);
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
\end{minipage}
|
|
|
&
|
|
|
$\Rightarrow$\qquad\qquad
|
|
|
&
|
|
|
\begin{minipage}{0.3\textwidth}
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
leaq (fun-ref |$f$|), |$\itm{lhs}'$|
|
|
|
\end{lstlisting}
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+leaq (FunRef(|$f$|)), |$\itm{lhs}'$|
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
\end{minipage}
|
|
|
\end{tabular} \\
|
|
|
|
|
@@ -14180,7 +14205,7 @@ useful in the \code{uncover\_live} pass for determining which
|
|
|
argument-passing registers are potentially read during the call.
|
|
|
|
|
|
For tail calls, the parameter passing is the same as non-tail calls:
|
|
|
-generate instructions to move the arguments into to the argument
|
|
|
+generate instructions to move the arguments into 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
|
|
@@ -14191,7 +14216,7 @@ argument that specifies where to jump and an integer that represents
|
|
|
the arity of the function being called.
|
|
|
|
|
|
Recall that we use the label \code{start} for the initial block of a
|
|
|
-program, and in Section~\ref{sec:select-Lvar} we recommended labeling
|
|
|
+program, and in Section~\ref{sec:select-Lvar} we recommend labeling
|
|
|
the conclusion of the program with \code{conclusion}, so that
|
|
|
$\RETURN{Arg}$ can be compiled to an assignment to \code{rax} followed
|
|
|
by a jump to \code{conclusion}. With the addition of function
|
|
@@ -14216,7 +14241,7 @@ to obtain unique labels.
|
|
|
The \code{IndirectCallq} instruction should be treated like
|
|
|
\code{Callq} regarding its written locations $W$, in that they should
|
|
|
include all the caller-saved registers. Recall that the reason for
|
|
|
-that is to force call-live variables to be assigned to callee-saved
|
|
|
+that is to force variables that are live across a function call to be assigned to callee-saved
|
|
|
registers or to be spilled to the stack.
|
|
|
|
|
|
Regarding the set of read locations $R$ the arity field of
|
|
@@ -14227,17 +14252,17 @@ instructions.
|
|
|
\subsection{Build Interference Graph}
|
|
|
\label{sec:build-interference-r4}
|
|
|
|
|
|
-With the addition of function definitions, we compute an interference
|
|
|
+With the addition of function definitions, we compute a separate interference
|
|
|
graph for each function (not just one for the whole program).
|
|
|
|
|
|
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
|
|
|
-\code{collect}. With the addition of functions to our language, we
|
|
|
-need to revisit this issue. Many functions perform allocation and
|
|
|
-therefore have calls to the collector inside of them. Thus, we should
|
|
|
+spill vector-typed variables that are live during a call to
|
|
|
+\code{collect}, the garbage collector. With the addition of functions to our language, we
|
|
|
+need to revisit this issue. Functions that perform allocation contain
|
|
|
+calls to the collector. Thus, we should
|
|
|
not only spill a vector-typed variable when it is live during a call
|
|
|
to \code{collect}, but we should spill the variable if it is live
|
|
|
-during any function call. Thus, in the \code{build\_interference} pass,
|
|
|
+during call to a user-defined function. Thus, in the \code{build\_interference} pass,
|
|
|
we recommend adding interference edges between call-live vector-typed
|
|
|
variables and the callee-saved registers (in addition to the usual
|
|
|
addition of edges between call-live variables and the caller-saved
|
|
@@ -14260,7 +14285,7 @@ instead of just once for the whole program.
|
|
|
In \code{patch\_instructions}, you should deal with the x86
|
|
|
idiosyncrasy that the destination argument of \code{leaq} must be a
|
|
|
register. Additionally, you should ensure that the argument of
|
|
|
-\code{TailJmp} is \itm{rax}, our reserved register---this is to make
|
|
|
+\code{TailJmp} is \itm{rax}, our reserved register---mostly to make
|
|
|
code generation more convenient, because we trample many registers
|
|
|
before the tail call (as explained in the next section).
|
|
|
|
|
@@ -14283,7 +14308,7 @@ a function, except the \code{retq} is replaced with \code{jmp *$\itm{arg}$}.
|
|
|
|
|
|
Regarding function definitions, you need to generate a prelude
|
|
|
and conclusion for each one. This code is similar to the prelude and
|
|
|
-conclusion that you generated for the \code{main} function in
|
|
|
+conclusion generated for the \code{main} function in
|
|
|
Chapter~\ref{ch:Lvec}. To review, the prelude of every function
|
|
|
should carry out the following steps.
|
|
|
% TODO: .align the functions!
|
|
@@ -14301,13 +14326,13 @@ should carry out the following steps.
|
|
|
\item Move the root stack pointer \code{r15} up by the size of the
|
|
|
root-stack frame for this function, which depends on the number of
|
|
|
spilled vectors. \label{root-stack-init}
|
|
|
-\item Initialize to zero all of the entries in the root-stack frame.
|
|
|
+\item Initialize to zero all new entries in the root-stack frame.
|
|
|
\item Jump to the start block.
|
|
|
\end{enumerate}
|
|
|
The prelude of the \code{main} function has one additional task: call
|
|
|
the \code{initialize} function to set up the garbage collector and
|
|
|
move the value of the global \code{rootstack\_begin} in
|
|
|
-\code{r15}. This should happen before step \ref{root-stack-init}
|
|
|
+\code{r15}. This initialization should happen before step \ref{root-stack-init}
|
|
|
above, which depends on \code{r15}.
|
|
|
|
|
|
The conclusion of every function should do the following.
|