Jeremy G. Siek 2 жил өмнө
parent
commit
9f6007ae19
1 өөрчлөгдсөн 32 нэмэгдсэн , 33 устгасан
  1. 32 33
      book.tex

+ 32 - 33
book.tex

@@ -8580,7 +8580,7 @@ abstract syntax.
 \label{sec:x86-if}
 \label{sec:x86-if}
 \index{subject}{x86}
 \index{subject}{x86}
 
 
-To implement the new logical operations, the
+To implement Booleans, the new logical operations, the
 comparison operations, and the \key{if} expression\python{ and
 comparison operations, and the \key{if} expression\python{ and
   statement}, we delve further into the x86
   statement}, we delve further into the x86
 language. Figures~\ref{fig:x86-1-concrete} and \ref{fig:x86-1} present
 language. Figures~\ref{fig:x86-1-concrete} and \ref{fig:x86-1} present
@@ -8593,13 +8593,17 @@ comparisons, and \racket{conditional} jumps.
   which we refer to as a \emph{basic block}\index{subject}{basic
   which we refer to as a \emph{basic block}\index{subject}{basic
     block}.}
     block}.}
 
 
-One challenge is that x86 does not provide an instruction that
-directly implements logical negation (\code{not} in \LangIf{} and
-\LangCIf{}).  However, the \code{xorq} instruction can be used to
-encode \code{not}.  The \key{xorq} instruction takes two arguments,
-performs a pairwise exclusive-or ($\mathrm{XOR}$) operation on each
-bit of its arguments, and writes the results into its second argument.
-Recall the following truth table for exclusive-or:
+As x86 does not provide direct support for Booleans, we take the usual
+approach of encoding Booleans as integers, with \code{True} as $1$ and
+\code{False} as $0$.
+
+Furthermore, x86 does not provide an instruction that directly
+implements logical negation (\code{not} in \LangIf{} and \LangCIf{}).
+However, the \code{xorq} instruction can be used to encode \code{not}.
+The \key{xorq} instruction takes two arguments, performs a pairwise
+exclusive-or ($\mathrm{XOR}$) operation on each bit of its arguments,
+and writes the results into its second argument.  Recall the following
+truth table for exclusive-or:
 \begin{center}
 \begin{center}
 \begin{tabular}{l|cc}
 \begin{tabular}{l|cc}
    & 0 & 1 \\ \hline
    & 0 & 1 \\ \hline
@@ -8763,26 +8767,28 @@ a \key{cmpq} instruction to set the EFLAGS register.
 \section{Shrink the \LangIf{} Language}
 \section{Shrink the \LangIf{} Language}
 \label{sec:shrink-Lif}
 \label{sec:shrink-Lif}
 
 
-The \LangIf{} language includes several features that are easily
-expressible with other features. For example, \code{and} and \code{or}
-are expressible using \code{if} as follows.
+The \code{shrink} pass translates some of the language features into
+other features, thereby reducing the kinds of expressions in the
+language. For example, the short-circuiting nature of the \code{and}
+and \code{or} logical operators can be expressed using \code{if} as
+follows.
 \begin{align*}
 \begin{align*}
   \CAND{e_1}{e_2} & \quad \Rightarrow \quad \CIF{e_1}{e_2}{\FALSE{}}\\
   \CAND{e_1}{e_2} & \quad \Rightarrow \quad \CIF{e_1}{e_2}{\FALSE{}}\\
   \COR{e_1}{e_2} & \quad \Rightarrow \quad \CIF{e_1}{\TRUE{}}{e_2}
   \COR{e_1}{e_2} & \quad \Rightarrow \quad \CIF{e_1}{\TRUE{}}{e_2}
 \end{align*}
 \end{align*}
 By performing these translations in the front end of the compiler,
 By performing these translations in the front end of the compiler,
-subsequent passes of the compiler do not need to deal with these features,
-thus making the passes shorter.
+subsequent passes of the compiler can be shorter.
 
 
 On the other hand, translations sometimes reduce the efficiency of the
 On the other hand, translations sometimes reduce the efficiency of the
 generated code by increasing the number of instructions. For example,
 generated code by increasing the number of instructions. For example,
-expressing subtraction in terms of negation
+expressing subtraction in terms of addition and negation
 \[
 \[
 \CBINOP{\key{-}}{e_1}{e_2} \quad \Rightarrow \quad
 \CBINOP{\key{-}}{e_1}{e_2} \quad \Rightarrow \quad
   \CBINOP{\key{+}}{e_1}{ \CUNIOP{\key{-}}{e_2} }
   \CBINOP{\key{+}}{e_1}{ \CUNIOP{\key{-}}{e_2} }
 \]
 \]
 produces code with two x86 instructions (\code{negq} and \code{addq})
 produces code with two x86 instructions (\code{negq} and \code{addq})
-instead of just one (\code{subq}).
+instead of just one (\code{subq}). Thus, we do not recommend
+translating subtraction into addition and negation.
 
 
 \begin{exercise}\normalfont\normalsize
 \begin{exercise}\normalfont\normalsize
 %
 %
@@ -8942,11 +8948,9 @@ condition must be a comparison.
 As a motivating example, consider the following program that has an
 As a motivating example, consider the following program that has an
 \key{if} expression nested in the condition of another \key{if}:%
 \key{if} expression nested in the condition of another \key{if}:%
 \python{\footnote{Programmers rarely write nested \code{if}
 \python{\footnote{Programmers rarely write nested \code{if}
-  expressions, but it is not uncommon for the condition of an
-  \code{if} statement to be a call of a function that also contains an
-  \code{if} statement.  When such a function is inlined, the result is
-  a nested \code{if} that requires the techniques discussed in this
-  section.}}
+    expressions, but they do write nested expressions involving
+    logical \code{and}, which, as we have seen, translates to
+    \code{if}.}}
 % cond_test_41.rkt, if_lt_eq.py
 % cond_test_41.rkt, if_lt_eq.py
 \begin{center}
 \begin{center}
 \begin{minipage}{0.96\textwidth}
 \begin{minipage}{0.96\textwidth}
@@ -9266,7 +9270,6 @@ def explicate_effect(e, cont, basic_blocks):
             ...
             ...
         case _:
         case _:
             ...
             ...
-
 def explicate_assign(rhs, lhs, cont, basic_blocks):
 def explicate_assign(rhs, lhs, cont, basic_blocks):
     match rhs:
     match rhs:
         case IfExp(test, body, orelse):
         case IfExp(test, body, orelse):
@@ -9275,7 +9278,6 @@ def explicate_assign(rhs, lhs, cont, basic_blocks):
             ...
             ...
         case _:
         case _:
             return [Assign([lhs], rhs)] + cont
             return [Assign([lhs], rhs)] + cont
-
 def explicate_pred(cnd, thn, els, basic_blocks):
 def explicate_pred(cnd, thn, els, basic_blocks):
     match cnd:
     match cnd:
         case Compare(left, [op], [right]):
         case Compare(left, [op], [right]):
@@ -9296,7 +9298,6 @@ def explicate_pred(cnd, thn, els, basic_blocks):
             return [If(Compare(cnd, [Eq()], [Constant(False)]),
             return [If(Compare(cnd, [Eq()], [Constant(False)]),
                        create_block(els, basic_blocks),
                        create_block(els, basic_blocks),
                        create_block(thn, basic_blocks))]
                        create_block(thn, basic_blocks))]
-
 def explicate_stmt(s, cont, basic_blocks):
 def explicate_stmt(s, cont, basic_blocks):
     match s:
     match s:
         case Assign([lhs], rhs):
         case Assign([lhs], rhs):
@@ -9305,7 +9306,6 @@ def explicate_stmt(s, cont, basic_blocks):
             return explicate_effect(value, cont, basic_blocks)
             return explicate_effect(value, cont, basic_blocks)
         case If(test, body, orelse):
         case If(test, body, orelse):
             ...
             ...
-
 def explicate_control(p):
 def explicate_control(p):
     match p:
     match p:
         case Module(body):
         case Module(body):
@@ -9757,7 +9757,7 @@ The \code{select\_instructions} pass translates \LangCIf{} to
 \racket{For $\Atm$, we have new cases for the Booleans.}
 \racket{For $\Atm$, we have new cases for the Booleans.}
 %
 %
 \python{We begin with the Boolean constants.}
 \python{We begin with the Boolean constants.}
-We take the usual approach of encoding them as integers.
+As previously discussed, we encode them as integers.
 \[
 \[
 \TRUE{} \quad\Rightarrow\quad \key{1}
 \TRUE{} \quad\Rightarrow\quad \key{1}
 \qquad\qquad
 \qquad\qquad
@@ -9846,7 +9846,7 @@ but use different condition codes for the conditional jump instruction.
 
 
 \python{Regarding the \key{return} statement, we recommend treating it
 \python{Regarding the \key{return} statement, we recommend treating it
   as an assignment to the \key{rax} register followed by a jump to the
   as an assignment to the \key{rax} register followed by a jump to the
-  conclusion of the \code{main} function.}
+  conclusion of the \code{main} function. (See section~\ref{sec:prelude-conclusion-cond} for more about the conclusion of \code{main}.)}
 
 
 \begin{exercise}\normalfont\normalsize
 \begin{exercise}\normalfont\normalsize
 Expand your \code{select\_instructions} pass to handle the new
 Expand your \code{select\_instructions} pass to handle the new
@@ -9953,11 +9953,9 @@ this instruction is particularly interesting because during
 compilation, we do not know which way a conditional jump will go. Thus
 compilation, we do not know which way a conditional jump will go. Thus
 we do not know whether to use the live-before set for the block
 we do not know whether to use the live-before set for the block
 associated with the $\itm{label}$ or the live-before set for the
 associated with the $\itm{label}$ or the live-before set for the
-following instruction.  However, there is no harm to the correctness
-of the generated code if we classify more locations as live than the
-ones that are truly live during one particular execution of the
-instruction. Thus, we can take the union of the live-before sets from
-the following instruction and from the mapping for $\itm{label}$ in
+following instruction. So we use both, by taking the union of the
+live-before sets from the following instruction and from the mapping
+for $\itm{label}$ in
 \racket{\code{label->live}}\python{\code{live\_before\_block}}.
 \racket{\code{label->live}}\python{\code{live\_before\_block}}.
 
 
 The auxiliary functions for computing the variables in an
 The auxiliary functions for computing the variables in an
@@ -10029,8 +10027,9 @@ pass.
 The second argument of the \key{cmpq} instruction must not be an
 The second argument of the \key{cmpq} instruction must not be an
 immediate value (such as an integer). So, if you are comparing two
 immediate value (such as an integer). So, if you are comparing two
 immediates, we recommend inserting a \key{movq} instruction to put the
 immediates, we recommend inserting a \key{movq} instruction to put the
-second argument in \key{rax}. As usual, \key{cmpq} may have at most
-one memory reference.
+second argument in \key{rax}.
+%
+As usual, \key{cmpq} may have at most one memory reference.
 %
 %
 The second argument of the \key{movzbq} must be a register.
 The second argument of the \key{movzbq} must be a register.