Skip to content

Commit 0d605e5

Browse files
committed
More on Con.
1 parent aba11f9 commit 0d605e5

2 files changed

Lines changed: 70 additions & 27 deletions

File tree

www/notes/con.scrbl

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,66 @@ if-expressions.
164164

165165
Suppose we want to compile @racket['(if (zero? 8) 2 3)]...
166166

167-
We already know how to compile the @racket['8], @racket['2], and
168-
@racket['3] part.
167+
We already know how to compile the @racket[8], @racket[2], and
168+
@racket[3] part.
169169

170-
What needs to happen? ...
170+
What needs to happen?
171+
172+
@itemlist[
173+
@item{Execute the code for @racket[8] leaving the result in @racket['rax],}
174+
@item{check whether @racket['rax] holds zero,}
175+
@item{if it does, execute the code for @racket[2],}
176+
@item{if it doesn't, execute the code for @racket[3].}
177+
]
178+
179+
We can determine whether @racket[8] evaluates to @racket[0] using a
180+
comparison instruction: @racket['(cmp rax 0)]. To do the conditional
181+
execution, we will need to jump to different parts of the code to
182+
either execute the code for @racket[2] or @racket[3]. There are
183+
several ways we could accomplish this, but we take the following
184+
approach: immediately after the comparison, do a conditional jump to
185+
the code for the else branch when non-zero. Should the jump not occur,
186+
the next instructions will carry out the evaluation of the then
187+
branch, then (unconditionally) jump over the else branch code.
188+
189+
To accomplish this, we will need two new labels: one for the else
190+
branch code and one for the end of the else branch code. The
191+
@racket[gensym] function can be used to generate symbols that have not
192+
appeared before.
193+
194+
In total, the code for this example would look like:
195+
196+
@racketblock[
197+
'((mov rax 8)
198+
(cmp rax 0)
199+
(jne if-else-begin)
200+
(mov rax 2)
201+
(jmp if-else-end)
202+
if-else-begin
203+
(mov rax 3)
204+
if-else-end)
205+
]
206+
207+
Notice that the @racket['(mov rax 8)], @racket['(mov rax 3)] and
208+
@racket['(mov rax 2)] parts are just the instructions generated by
209+
compiling @racket[8], @racket[2] and @racket[3]. Generalizing from
210+
this, we arrive at the following code for the compiler:
211+
212+
@racketblock[
213+
(let ((c0 (compile-e e0))
214+
(c1 (compile-e e1))
215+
(c2 (compile-e e2))
216+
(l0 (gensym "if-else-begin"))
217+
(l1 (gensym "if-else-end")))
218+
'(,@c0
219+
(cmp rax 0)
220+
(jne ,l0)
221+
,@c1
222+
(jmp ,l1)
223+
,l0
224+
,@c2
225+
,l1))
226+
]
171227

172228

173229
@ex[

www/notes/con/compile.rkt

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,14 @@
2222
[`(if (zero? ,e0) ,e1 ,e2)
2323
(let ((c0 (compile-e e0))
2424
(c1 (compile-e e1))
25-
(c2 (compile-e e2)))
26-
(match (gen-if-labels)
27-
[(list if-f if-x)
28-
`(,@c0
29-
(cmp rax 0)
30-
(jne ,if-f)
31-
,@c1
32-
(jmp ,if-x)
33-
,if-f
34-
,@c2
35-
,if-x)]))]))
36-
37-
;; -> [List Label Label]
38-
;; Guaranteed to be unique on each call
39-
(define gen-if-labels
40-
(let ((i 0))
41-
(λ ()
42-
(set! i (add1 i))
43-
(list (lab "f" i)
44-
(lab "x" i)))))
45-
46-
;; String Integer -> Symbol
47-
(define (lab s i)
48-
(string->symbol (string-append "if_" s "_" (number->string i))))
25+
(c2 (compile-e e2))
26+
(l0 (gensym "if"))
27+
(l1 (gensym "if")))
28+
`(,@c0
29+
(cmp rax 0)
30+
(jne ,l0)
31+
,@c1
32+
(jmp ,l1)
33+
,l0
34+
,@c2
35+
,l1))]))

0 commit comments

Comments
 (0)