Jeremy Siek 4 years ago
parent
commit
dda7b592f6
2 changed files with 371 additions and 88 deletions
  1. 370 88
      book.tex
  2. 1 0
      defs.tex

+ 370 - 88
book.tex

@@ -81,8 +81,8 @@
 \lstset{%
 \lstset{%
 language=Lisp,
 language=Lisp,
 basicstyle=\ttfamily\small,
 basicstyle=\ttfamily\small,
-morekeywords={seq,assign,program,block,define,lambda,match,goto,if,else,then,struct,Integer,Boolean,Vector,Void},
-deletekeywords={read},
+morekeywords={seq,assign,program,block,define,lambda,match,goto,if,else,then,struct,Integer,Boolean,Vector,Void,while},
+deletekeywords={read,mapping},
 escapechar=|,
 escapechar=|,
 columns=flexible,
 columns=flexible,
 moredelim=[is][\color{red}]{~}{~},
 moredelim=[is][\color{red}]{~}{~},
@@ -5030,7 +5030,7 @@ Let $B_1$ be the result of \code{explicate-tail} on the ``then''
 branch and $G_0$ and let $B_2$ be the result of \code{explicate-tail}
 branch and $G_0$ and let $B_2$ be the result of \code{explicate-tail}
 on the ``else'' branch and $G_0$.  Let $B_3$ be the result of applying
 on the ``else'' branch and $G_0$.  Let $B_3$ be the result of applying
 \code{explicate-pred} to the condition of the \key{if}, $B_1$, and
 \code{explicate-pred} to the condition of the \key{if}, $B_1$, and
-$B_2$.  Then the \key{if} as a whole translates to $B_3$.
+$B_2$.  Then the \key{if} as a whole translates to promise $B_3$.
 \[
 \[
     (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_3
     (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_3
 \]
 \]
@@ -5053,8 +5053,8 @@ assignment positions.  Let $B_2$ be the result of applying
 $G_1$.  Let $B_3$ be the result of applying \code{explicate-assign} to
 $G_1$.  Let $B_3$ be the result of applying \code{explicate-assign} to
 the ``else'' branch, variable $x$, and $G_1$. Finally, let $B_4$ be
 the ``else'' branch, variable $x$, and $G_1$. Finally, let $B_4$ be
 the result of applying \code{explicate-pred} to the predicate
 the result of applying \code{explicate-pred} to the predicate
-$\itm{cnd}$ and the blocks $B_2$ and $B_3$. The \key{if} as a whole
-translates to the block $B_4$.
+$\itm{cnd}$ and the promises $B_2$ and $B_3$. The \key{if} as a whole
+translates to the promise $B_4$.
 \[
 \[
 (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_4
 (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_4
 \]
 \]
@@ -6363,6 +6363,8 @@ should all be treated as complex operands. A new case for
 handled carefully to prevent the \code{Prim} node from being separated
 handled carefully to prevent the \code{Prim} node from being separated
 from its enclosing \code{HasType}.
 from its enclosing \code{HasType}.
 
 
+TODO: add the grammar for the output language
+
 
 
 \section{Explicate Control and the $C_2$ language}
 \section{Explicate Control and the $C_2$ language}
 \label{sec:explicate-control-r3}
 \label{sec:explicate-control-r3}
@@ -7510,6 +7512,7 @@ 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
 that changes function references from just a symbol $f$ to
 $\FUNREF{f}$. This pass is named \code{reveal-functions} and the
 $\FUNREF{f}$. This pass is named \code{reveal-functions} and the
 output language, $F_1$, is defined in Figure~\ref{fig:f1-syntax}.
 output language, $F_1$, is defined in Figure~\ref{fig:f1-syntax}.
+The concrete syntax for a function reference is $\CFUNREF{f}$.
 
 
 \begin{figure}[tp]
 \begin{figure}[tp]
 \centering
 \centering
@@ -7602,7 +7605,7 @@ $\Rightarrow$
 \end{tabular}
 \end{tabular}
 
 
 
 
-\section{Remove Complex Operators and Operands}
+\section{Remove Complex Operands}
 \label{sec:rco-r4}
 \label{sec:rco-r4}
 
 
 The primary decisions to make for this pass is whether to classify
 The primary decisions to make for this pass is whether to classify
@@ -7618,6 +7621,9 @@ 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
 statement with a left-hand side that can serve as the target of the
 \code{leaq}.
 \code{leaq}.
 
 
+TODO: add the output grammar
+
+
 \section{Explicate Control and the $C_3$ language}
 \section{Explicate Control and the $C_3$ language}
 \label{sec:explicate-control-r4}
 \label{sec:explicate-control-r4}
 
 
@@ -8432,7 +8438,7 @@ $\Rightarrow$
 &
 &
 \begin{minipage}{0.4\textwidth}
 \begin{minipage}{0.4\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
-(vector |\itm{name}| |\itm{fvs}| ...)
+(vector (fun-ref |\itm{name}|) |\itm{fvs}| ...)
 \end{lstlisting}
 \end{lstlisting}
 \end{minipage}
 \end{minipage}
 \end{tabular}  \\
 \end{tabular}  \\
@@ -8792,7 +8798,7 @@ sequencing side effects: the \code{begin} expression.  It consists of
 one or more expressions that are evaluated left-to-right.  The result
 one or more expressions that are evaluated left-to-right.  The result
 of the last expression is also the result of the \code{begin}.  The
 of the last expression is also the result of the \code{begin}.  The
 rest of the expressions are only evaluated for their side effects.
 rest of the expressions are only evaluated for their side effects.
-
+%
 The concrete syntax of $R_8$ is defined in
 The concrete syntax of $R_8$ is defined in
 Figure~\ref{fig:r8-concrete-syntax} and its abstract syntax is defined
 Figure~\ref{fig:r8-concrete-syntax} and its abstract syntax is defined
 in Figure~\ref{fig:r8-syntax}.
 in Figure~\ref{fig:r8-syntax}.
@@ -8861,10 +8867,11 @@ in Figure~\ref{fig:r8-syntax}.
 
 
 At first glance, the translation of these language features to x86
 At first glance, the translation of these language features to x86
 seems to be trivial because the $C_3$ intermediate language already
 seems to be trivial because the $C_3$ intermediate language already
-supports assignment, \code{goto}, conditional branching, and
-sequencing. However, there are two complications that arise, which we
-discuss in the next two sections. After that we introduce one new
-compiler pass and the changes necessary to the existing passes.
+supports all of the ingredients that we need: assignment, \code{goto},
+conditional branching, and sequencing. However, there are two
+complications that arise, which we discuss in the next two
+sections. After that we introduce one new compiler pass and the
+changes necessary to the existing passes.
 
 
 \section{Assignment and Lexically Scoped Functions}
 \section{Assignment and Lexically Scoped Functions}
 \label{sec:assignment-scoping}
 \label{sec:assignment-scoping}
@@ -8873,15 +8880,16 @@ The addition of assignment raises a problem with our approach to
 implementing lexically-scoped functions. Consider the following
 implementing lexically-scoped functions. Consider the following
 example in which function \code{f} has a free variable \code{x} that
 example in which function \code{f} has a free variable \code{x} that
 is changed after \code{f} is created but before the call to \code{f}.
 is changed after \code{f} is created but before the call to \code{f}.
-% similar to loop_test_5.rkt
+% loop_test_11.rkt
 \begin{lstlisting}
 \begin{lstlisting}
 (let ([x 0])
 (let ([x 0])
   (let ([y 0])
   (let ([y 0])
-    (let ([f (lambda: ([z : Integer]) : Integer (+ x z))])
-      (begin
-        (set! x 10)
-        (set! y 12)
-        (+ 20 (f y))))))
+    (let ([z 20])
+      (let ([f (lambda: ([a : Integer]) : Integer (+ a (+ x z)))])
+        (begin
+          (set! x 10)
+          (set! y 12)
+          (f y))))))
 \end{lstlisting}
 \end{lstlisting}
 The correct output for this example is \code{42} because the call to
 The correct output for this example is \code{42} because the call to
 \code{f} is required to use the current value of \code{x} (which is
 \code{f} is required to use the current value of \code{x} (which is
@@ -8933,10 +8941,10 @@ we one more problem to discuss.
 \section{Cyclic Control Flow and Dataflow Analysis}
 \section{Cyclic Control Flow and Dataflow Analysis}
 \label{sec:dataflow-analysis}
 \label{sec:dataflow-analysis}
 
 
-Up until now the control-flow graphs generated in
+Up until this point the control-flow graphs generated in
 \code{explicate-control} were guaranteed to be acyclic. However, each
 \code{explicate-control} were guaranteed to be acyclic. However, each
-\code{while} loop will introduce a cycle in the control-flow graph.
-But does this matter? 
+\code{while} loop introduces a cycle in the control-flow graph.
+But does that matter?
 %
 %
 Indeed it does.  Recall that for register allocation, the compiler
 Indeed it does.  Recall that for register allocation, the compiler
 performs liveness analysis to determine which variables can share the
 performs liveness analysis to determine which variables can share the
@@ -8990,136 +8998,410 @@ 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
 \code{block5} jumps to \code{block7} and vice versa, so it seems that
 we are stuck.
 we are stuck.
 
 
-The way out of this impass came from the realization that one can
-compute an under-approximation of the live-before set for each block
-by starting out with an empty live-after set. Furthmore, the
-under-approximations can be improved by updating the live-after set
-for each block using the under-approximated live-before sets from the
-other blocks. In fact, by iterating this process, the
-under-approximations eventually become the correct solutions!
+The way out of this impass comes from the realization that one can
+perfom 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
+under-approximations for each block can be improved by 1) updating the
+live-after set for each block using the approximate live-before sets
+from the other blocks and 2) perform liveness analysis again on each
+block.  In fact, by iterating this process, the under-approximations
+eventually become the correct solutions!
 %
 %
-This approach is applicable to many static analysis problems and goes
-by the name \emph{dataflow analysis}\index{dataflow analysis}.  It was
-invented by \citet{Kildall:1973vn} in his Ph.D. thesis at the
-University of Washington.
+This approach of iteratively analyzing a control-flow graph is
+applicable to many static analysis problems and goes by the name
+\emph{dataflow analysis}\index{dataflow analysis}.  It was invented by
+\citet{Kildall:1973vn} in his Ph.D. thesis at the University of
+Washington.
 
 
 Let us apply this approach to the above example. We use the empty set
 Let us apply this approach to the above example. We use the empty set
-for the initial live-before set for each block. Let $M_0$ be the
-following mapping from label names to sets of locations.
+for the initial live-before set for each block. Let $m_0$ be the
+following mapping from label names to sets of locations (variables and
+registers).
 \begin{center}
 \begin{center}
 \begin{lstlisting}
 \begin{lstlisting}
-mainstart: { }
-block5: { }
-block7: { }
-block8: { }
+mainstart: {}
+block5: {}
+block7: {}
+block8: {}
 \end{lstlisting}
 \end{lstlisting}
 \end{center}
 \end{center}
 Using the above live-before approximations, we determine the
 Using the above live-before approximations, we determine the
-live-after for each block and then apply liveness analysis to it.
-This produces the following approximate live-before sets for each
-block.
+live-after for each block and then apply liveness analysis to each
+block.  This produces our next approximation $m_1$ of the live-before
+sets.
 \begin{center}
 \begin{center}
   \begin{lstlisting}
   \begin{lstlisting}
 mainstart: {}
 mainstart: {}
-block5: { i2 }
-block7: { i2, sum1 }
-block8: { rsp, sum1 }
+block5: {i2}
+block7: {i2, sum1}
+block8: {rsp, sum1}
 \end{lstlisting}
 \end{lstlisting}
 \end{center}
 \end{center}
 
 
 For the second round, the live-after for \code{mainstart} is the
 For the second round, the live-after for \code{mainstart} is the
-current live-before for \code{block5}, which is \code{\{ i2 \}}.  So
-the approximate live-before for \code{mainstart} remains the empty
-set. The live-after for \code{block5} is the union of the
-live-before's for \code{block7} and \code{block8}, which is \code{\{
-  i2 , rsp, sum1 \}}. So the approximate live-before for \code{block5}
-is \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 approximate live-before of \code{block7}
-remains \code{\{ i2, sum1 \}}.
+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
+\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.
 \begin{center}
 \begin{center}
   \begin{lstlisting}
   \begin{lstlisting}
 mainstart: {}
 mainstart: {}
-block5: { i2, rsp, sum1 }
-block7: { i2, sum1 }
-block8: { rsp, sum1 }
+block5: {i2, rsp, sum1}
+block7: {i2, sum1}
+block8: {rsp, sum1}
 \end{lstlisting}
 \end{lstlisting}
 \end{center}
 \end{center}
 In the preceeding iteration, only \code{block5} changed, so we can
 In the preceeding iteration, only \code{block5} changed, so we can
 limit our attention to \code{mainstart} and \code{block7}, the two
 limit our attention to \code{mainstart} and \code{block7}, the two
 blocks that jump to \code{block5}.  As a result, the live-before sets
 blocks that jump to \code{block5}.  As a result, the live-before sets
 for \code{mainstart} and \code{block7} are updated to include
 for \code{mainstart} and \code{block7} are updated to include
-\code{rsp}.
+\code{rsp}, yielding the following approximation $m_3$.
 \begin{center}
 \begin{center}
   \begin{lstlisting}
   \begin{lstlisting}
-mainstart: { rsp }
-block5: { i2, rsp, sum1 }
-block7: { i2, rsp, sum1 }
-block8: { rsp, sum1 }
+mainstart: {rsp}
+block5: {i2, rsp, sum1}
+block7: {i2, rsp, sum1}
+block8: {rsp, sum1}
 \end{lstlisting}
 \end{lstlisting}
 \end{center}
 \end{center}
 Because \code{block7} changed, we analyze \code{block5} once more, but
 Because \code{block7} changed, we analyze \code{block5} once more, but
 its live-before set remains \code{\{ i2, rsp, sum1 \}}.  At this point
 its live-before set remains \code{\{ i2, rsp, sum1 \}}.  At this point
-our approximations have converged on the actual solution.
+our approximations have converged, so $m_3$ is the solution.
 
 
 This iteration process is guaranteed to converge to a solution by the
 This iteration process is guaranteed to converge to a solution by the
 Kleene Fixed-Point Theorem, a general theorem about functions on
 Kleene Fixed-Point Theorem, a general theorem about functions on
-lattices~\citet{Kleene:1952aa}. Roughly speaking, a lattice is some
-collection $L$ whose elements are partially ordered by a relation
-$\sqsubseteq$ and $L$ contains a least element $\bot$ (bottom). For
-liveness analysis, a mapping $M$ of block labels to sets of locations
-is a single element in the lattice. We can order these mappings
-pointwise, using set inclusion to compare sets of live locations.  So
-given any two mappings $M_i$ and $M_j$, $M_i \sqsubseteq M_j$ when
-$M_i(\ell) \subseteq M_j(\ell)$ for every block label $\ell$ in the
-program. Let $M_\bot$ be the mapping that sends every label to the
-emptyset, i.e., $M_{\bot}(\ell) = \emptyset$.  Thus, $M_{\bot}$ is the
-bottom element of this lattice.
+lattices~\citep{Kleene:1952aa}. Roughly speaking, a \emph{lattice} is
+any collection that comes with a partial ordering $\sqsubseteq$ on its
+elements, a least element $\bot$ (pronounced bottom), and a join
+operator $\sqcup$.\index{lattice}\index{bottom}\index{partial
+  ordering}\index{join}\footnote{Technically speaking, we will be
+  working with join semi-lattices.} When two elements are ordered $m_i
+\sqsubseteq m_j$, it means that $m_j$ contains at least as much
+information as $m_i$, so we can think of $m_j$ as a better-or-equal
+approximation than $m_i$.  The bottom element $\bot$ represents the
+complete lack of information, i.e., the worst approximation.  The join
+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
+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
+the lattice $L$ by taking its elements to be sets of locations, the
+ordering to be set inclusion ($\subseteq$), the bottom to be the empty
+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
+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$.
 
 
 We can think of one iteration of liveness analysis as being a function
 We can think of one iteration of liveness analysis as being a function
-$f$ on this lattice. It takes a mapping as input and computes a new
+$f$ on the lattice $M$. It takes a mapping as input and computes a new
 mapping.
 mapping.
 \[
 \[
-   f(M_i) = M_{i+1}
+   f(m_i) = m_{i+1}
 \]
 \]
-Next let us think for a moment about what a final solution $M_s$
+Next let us think for a moment about what a final solution $m_s$
 should look like. If we perform liveness analysis using the solution
 should look like. If we perform liveness analysis using the solution
-$M_s$ as input, we should get $M_s$ again as the output. That is, the
+$m_s$ as input, we should get $m_s$ again as the output. That is, the
 solution should be a \emph{fixed point} of the function $f$.\index{fixed point}
 solution should be a \emph{fixed point} of the function $f$.\index{fixed point}
 \[
 \[
-   f(M_s) = M_s
+   f(m_s) = m_s
 \]
 \]
 Furthermore, the solution should only include locations that are
 Furthermore, the solution should only include locations that are
 forced to be there by performing liveness analysis on the program, so
 forced to be there by performing liveness analysis on the program, so
 the solution should be the \emph{least} fixed point.\index{least fixed point}
 the solution should be the \emph{least} fixed point.\index{least fixed point}
 
 
 The Kleene Fixed-Point Theorem states that if a function $f$ is
 The Kleene Fixed-Point Theorem states that if a function $f$ is
-monotone (larger inputs produce larger outputs), then the least fixed
-point of $f$ is the largest element of what is called the ascending
-Kleene chain:\index{Kleene Fixed-Point Theorem}
+monotone (better inputs produce better outputs), then the least fixed
+point of $f$ is the greatest element of the \emph{ascending Kleene
+  chain} obtained by starting at $\bot$ and iterating $f$ as
+follows.\index{Kleene Fixed-Point Theorem}
 \[
 \[
 \bot \sqsubseteq f(\bot) \sqsubseteq f(f(\bot)) \sqsubseteq \cdots
 \bot \sqsubseteq f(\bot) \sqsubseteq f(f(\bot)) \sqsubseteq \cdots
   \sqsubseteq f^n(\bot) \sqsubseteq \cdots
   \sqsubseteq f^n(\bot) \sqsubseteq \cdots
 \]
 \]
-Some lattices have an infinite number of elements and functions on
-them that keep going up forever. Fortunately for liveness analysis,
-this is not the case because there are only a finite number of
-variables in the program. Thus, the ascending chains always ``top
-out'' at some fixed point after some number of iterations.
+When a lattice contains only finitely-long ascending chains, then
+every Kleene chain tops out at some fixed point after a number of
+iterations of $f$.
 \[
 \[
 \bot \sqsubseteq f(\bot) \sqsubseteq f(f(\bot)) \sqsubseteq \cdots
 \bot \sqsubseteq f(\bot) \sqsubseteq f(f(\bot)) \sqsubseteq \cdots
-\sqsubseteq f^k(\bot) = f^{k+1}(\bot) = f^{k+2}(\bot)
+\sqsubseteq f^k(\bot) = f^{k+1}(\bot) = m_s
 \]
 \]
 
 
+The liveness analysis is indeed a monotone function and the lattice
+$M$ only has finitely-long ascending chains because there are only a
+finite number of variables and blocks in the program. Thus we are
+guaranteed that iteratively applying liveness analysis to all blocks
+in the program will eventually produce the least fixed point solution.
 
 
+Next let us consider dataflow analysis in general and discuss the
+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
+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
+\code{input} for the node is computed by taking the join of the
+abstract states of all the predecessor nodes. The \code{transfer}
+function is then applied to obtain the \code{output} abstract
+state. If the output differs from the previous state for this block,
+the mapping for this block is updated and its successor nodes are
+pushed onto the work list.
+
+\begin{figure}[tb]
+\begin{lstlisting}
+(define (analyze-dataflow G transfer bottom join)
+  (define mapping (make-hash))
+  (for ([v (in-vertices G)])
+    (dict-set! mapping v bottom))
+  (define worklist (make-queue))
+  (for ([v (in-vertices G)])
+    (enqueue! worklist v))
+  (define trans-G (transpose G))
+  (while (not (queue-empty? worklist))
+    (define node (dequeue! worklist)) 
+    (define input (for/fold ([state bottom])
+                            ([pred (in-neighbors trans-G node)])
+                    (join state (dict-ref mapping pred))))
+    (define output (transfer node input))
+    (cond [(not (equal? output (dict-ref mapping node)))
+           (dict-set! mapping node output)
+           (for ([v (in-neighbors G node)])
+             (enqueue! worklist v))]))
+  mapping)
+\end{lstlisting}
+\caption{Generic work list algorithm for dataflow analysis}
+  \label{fig:generic-dataflow}
+\end{figure}
 
 
-
+Having discussed the two complications that arise from adding support
+for assignment and loops, we turn to discussing the one new compiler
+pass and the significant changes to existing passes.
 
 
 \section{Convert Assignments}
 \section{Convert Assignments}
 \label{sec:convert-assignments}
 \label{sec:convert-assignments}
 
 
+Recall that in Section~\ref{sec:assignment-scoping} we learned that
+the combination of assignments and lexically-scoped functions requires
+that we box those variables that are both assigned-to and that appear
+free inside a \code{lambda}. The purpose of the
+\code{convert-assignments} pass is to carry out that transformation.
+We recommend placing this pass after \code{uniquify} but before
+\code{reveal-functions}.
 
 
+Consider again the first example from
+Section~\ref{sec:assignment-scoping}:
+\begin{lstlisting}
+(let ([x 0])
+  (let ([y 0])
+    (let ([z 20])
+      (let ([f (lambda: ([a : Integer]) : Integer (+ a (+ x z)))])
+        (begin
+          (set! x 10)
+          (set! y 12)
+          (f y))))))
+\end{lstlisting}
+The variables \code{x} and \code{y} are assigned-to.  The variables
+\code{x} and \code{z} occur free inside the \code{lambda}. Thus,
+variable \code{x} needs to be boxed but not \code{y} and \code{z}.
+The boxing of \code{x} consists of three transformations: initialize
+\code{x} with a vector, replace reads from \code{x} with
+\code{vector-ref}'s, and replace each \code{set!} on \code{x} with a
+\code{vector-set!}. The output of \code{convert-assignments} for this
+example is as follows.
+\begin{lstlisting}
+(define (main) : Integer
+  (let ([x0 (vector 0)])
+    (let ([y1 0])
+      (let ([z2 20])
+        (let ([f4 (lambda: ([a3 : Integer]) : Integer
+                      (+ a3 (+ (vector-ref x0 0) z2)))])
+          (begin 
+            (vector-set! x0 0 10)
+            (set! y1 12)
+            (f4 y1)))))))
+\end{lstlisting}
+
+\paragraph{Assigned \& Free}
+
+We recommend defining an auxilliary 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
+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
+$\itm{rhs}$ produces $\itm{rhs}'$, $A_r$, and $F_r$ and the recursive
+call on the $\itm{body}$ produces $\itm{body}'$, $A_b$, and $F_b$. If
+$x$ is in $A_b\cap F_b$, then transforms the \code{Let} as follows.
+\begin{lstlisting}
+  (Let |$x$| |$rhs$| |$body$|)
+  |$\Rightarrow$|
+  (Let (AssignedFree |$x$|) |$rhs'$| |$body'$|)
+\end{lstlisting}
+If $x$ is not in $A_b\cap F_b$ then omit the use of \code{AssignedFree}.
+The set of assigned variables for this \code{Let} is
+$A_r \cup (A_b - \{x\})$
+and the set of variables free in lambda's is
+$F_r \cup (F_b - \{x\})$.
+
+The case for $\SETBANG{x}{\itm{rhs}}$ is straightforward but
+important. Recursively process \itm{rhs} to obtain \itm{rhs'}, $A_r$,
+and $F_r$. The result is $\SETBANG{x}{\itm{rhs'}}$, $\{x\} \cup A_r$,
+and $F_r$.
+
+The case for $\LAMBDA{\itm{params}}{T}{\itm{body}}$ is a bit more
+involved.  Let \itm{body'}, $A_b$, and $F_b$ be the result of
+recursively processing \itm{body}. Wrap each of parameter that occurs
+in $A_b \cap F_b$ with \code{AssignedFree} to produce \itm{params'}.
+Let $P$ be the set of parameter names in \itm{params}.  The result is
+$\LAMBDA{\itm{params'}}{T}{\itm{body'}}$, $A_b - P$, and $(F_b \cup
+\mathrm{FV}(\itm{body})) - P$, where $\mathrm{FV}$ computes the free
+variables of an expression (see Chapter~\ref{ch:lambdas}).
+
+\paragraph{Convert Assignments}
+
+Next we discuss the \code{convert-assignment} pass with its auxiliary
+functions for expressions and definitions. The function for
+expressions, \code{cnvt-assign-exp}, should take an expression and a
+set of assigned-and-free variables (obtained from the result of
+\code{assigned\&free}. In the case for $\VAR{x}$, if $x$ is
+assigned-and-free, then unbox it by translating $\VAR{x}$ to a
+\code{vector-ref}.
+\begin{lstlisting}
+  (Var |$x$|)
+  |$\Rightarrow$|
+  (Prim 'vector-ref (list (Var |$x$|) (Int 0)))
+\end{lstlisting}
+%
+In the case for $\LET{\LP\code{AssignedFree}\,
+  x\RP}{\itm{rhs}}{\itm{body}}$, recursively process \itm{rhs} to
+obtain \itm{rhs'}.  Next, recursively process \itm{body} to obtain
+\itm{body'} but with $x$ added to the set of assigned-and-free
+variables.  Translate the let-expression as follows to bind $x$ to a
+boxed value.
+\begin{lstlisting}
+  (Let (AssignedFree |$x$|) |$rhs$| |$body$|)
+  |$\Rightarrow$|
+  (Let |$x$| (Prim 'vector (list |$rhs'$|)) |$body'$|)
+\end{lstlisting}
+%
+In the case for $\SETBANG{x}{\itm{rhs}}$, recursively process
+\itm{rhs} to obtain \itm{rhs'}.  If $x$ is in the assigned-and-free
+variables, translate the \code{set!} into a \code{vector-set!}
+as follows.
+\begin{lstlisting}
+  (SetBang |$x$| |$\itm{rhs}$|)
+  |$\Rightarrow$|
+  (Prim 'vector-set! (list (Var |$x$|) (Int 0) |$\itm{rhs'}$|))
+\end{lstlisting}
+%
+The case for \code{Lambda} is non-trivial, but it is similar to the
+case for function definitions, which we discuss next.
 
 
+The auxiliary function for definitions, \code{cnvt-assign-def},
+applies assignment conversion to function definitions.
+We translate a function definition as follows.
+\begin{lstlisting}
+  (Def |$f$| |$\itm{params}$| |$T$| |$\itm{info}$| |$\itm{body_1}$|)
+  |$\Rightarrow$|
+  (Def |$f$| |$\itm{params'}$| |$T$| |$\itm{info}$| |$\itm{body_4}$|)
+\end{lstlisting}
+So it remains to explain \itm{params'} and $\itm{body}_4$.
+Let \itm{body_2}, $A_b$, and $F_b$ be the result of
+\code{assigned\&free} on $\itm{body_1}$.
+Let $P$ be the parameter names in \itm{params}.
+We then apply \code{cnvt-assign-exp} to $\itm{body_2}$ to
+obtain \itm{body_3}, passing $A_b \cap F_b \cap P$
+as the set of assigned-and-free variables.
+Finally, we obtain \itm{body_4} by wrapping \itm{body_3}
+in a sequence of let-expressions that box the parameters
+that are in $A_b \cap F_b$.
+%
+Regarding \itm{params'}, change the names of the parameters that are
+in $A_b \cap F_b$ to maintain uniqueness (and so the let-bound
+variables can retain the original names). Recall the second example in
+Section~\ref{sec:assignment-scoping} involving a counter
+abstraction. The following is the output of assignment version for
+function \code{f}.
+\begin{lstlisting}
+(define (f0 [x1 : Integer]) : (Vector ( -> Integer) ( -> Void))
+  (vector
+   (lambda: () : Integer x1)
+   (lambda: () : Void (set! x1 (+ 1 x1)))))
+|$\Rightarrow$|
+(define (f0 [param_x1 : Integer]) : (Vector (-> Integer) (-> Void))
+  (let ([x1 (vector param_x1)])
+    (vector (lambda: () : Integer (vector-ref x1 0))
+             (lambda: () : Void
+                (vector-set! x1 0 (+ 1 (vector-ref x1 0)))))))
+\end{lstlisting}
+
+
+\section{Remove Complex Operands}
+\label{sec:rco-loop}
+
+
+TODO: define the output grammar
+
+
+\begin{lstlisting}
+(let ([x0 10])
+  (let ([y1 0])
+    (+ (+ (begin (set! y1 (read)) x0)
+          (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)))))))
+\end{lstlisting}
+
+
+
+
+
+\section{Explicate Control}
+\label{sec:explicate-loop}
+
+
+\section{Register Allocation}
+\label{sec:register-allocation-loop}
+
+
+%\section{Remove Jumps}
+%\label{sec:remove-jumps-loop}
+
+
+\section{Select Instructions}
+\label{sec:select-instructions-loop}
 
 
 
 
 
 

+ 1 - 0
defs.tex

@@ -66,6 +66,7 @@
 \newcommand{\TAILCALL}[2]{\key{(TailCall}\;#1\;#2\code{)}}
 \newcommand{\TAILCALL}[2]{\key{(TailCall}\;#1\;#2\code{)}}
 \newcommand{\FUNDEF}[5]{\key{(Def}~#1~#2~#3~#4~#5\code{)}}
 \newcommand{\FUNDEF}[5]{\key{(Def}~#1~#2~#3~#4~#5\code{)}}
 \newcommand{\FUNREF}[1]{\key{(FunRef}\;#1\code{)}}
 \newcommand{\FUNREF}[1]{\key{(FunRef}\;#1\code{)}}
+\newcommand{\CFUNREF}[1]{\key{(fun-ref}\;#1\code{)}}
 \newcommand{\LAMBDA}[3]{\key{(Lambda}~#1~#2~#3\code{)}}
 \newcommand{\LAMBDA}[3]{\key{(Lambda}~#1~#2~#3\code{)}}
 \newcommand{\CLAMBDA}[3]{\LP\key{lambda:}\,#1\,\key{:}\,#2\;\Exp\RP}
 \newcommand{\CLAMBDA}[3]{\LP\key{lambda:}\,#1\,\key{:}\,#2\;\Exp\RP}
 \newcommand{\INJECT}[2]{\LP\key{Inject}~#1~#2\RP}
 \newcommand{\INJECT}[2]{\LP\key{Inject}~#1~#2\RP}