Skip to content

Commit 5c07e1a

Browse files
committed
2 parents af006f5 + d9e8c83 commit 5c07e1a

File tree

4 files changed

+134
-68
lines changed

4 files changed

+134
-68
lines changed

conditionals.rkt

Lines changed: 78 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212

1313
(inherit liveness-ss first-offset variable-size in-memory?)
1414

15+
(define/public (comparison-ops)
16+
(set 'eq? '< '<= '> '>=))
17+
1518
(define/override (primitives)
1619
(set-union (super primitives)
17-
(set 'eq? 'and 'or 'not)))
20+
(comparison-ops)
21+
(set 'and 'or 'not)))
1822

1923
(define/public (insert-type-node node ty)
2024
(match node
@@ -24,6 +28,39 @@
2428

2529
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2630
;; type-check : env -> S1 -> S1 (new pass)
31+
32+
(define/public (binary-op-types)
33+
'((+ . ((Integer Integer) . Integer))
34+
(- . ((Integer Integer) . Integer))
35+
(* . ((Integer Integer) . Integer))
36+
(and . ((Boolean Boolean) . Boolean))
37+
(or . ((Boolean Boolean) . Boolean))
38+
(< . ((Integer Integer) . Boolean))
39+
(<= . ((Integer Integer) . Boolean))
40+
(> . ((Integer Integer) . Boolean))
41+
(>= . ((Integer Integer) . Boolean))
42+
))
43+
44+
(define/public (unary-op-types)
45+
'((- . ((Integer) . Integer))
46+
(not . ((Boolean) . Boolean))))
47+
48+
(define/public (nullary-op-types)
49+
'((read . (() . Integer))))
50+
51+
(define/public (type-check-op op ts)
52+
(define table
53+
(cond
54+
[(eq? 2 (length ts)) (binary-op-types)]
55+
[(eq? 1 (length ts)) (unary-op-types)]
56+
[else (nullary-op-types)]))
57+
(let ([pts (car (cdr (assq op table)))]
58+
[ret (cdr (cdr (assq op table)))])
59+
(unless (equal? ts pts)
60+
(error "argument type does not match parameter type"
61+
(list ts pts)))
62+
ret))
63+
2764
(define/public (type-check env)
2865
(lambda (e)
2966
(vomit "conditionals/type-check" e env)
@@ -59,30 +96,7 @@
5996
[`(,op ,es ...) #:when (set-member? (primitives) op)
6097
(define-values (new-es ts)
6198
(for/lists (exprs types) ([e es]) ((type-check env) e)))
62-
(define binary-ops
63-
'((+ . ((Integer Integer) . Integer))
64-
(- . ((Integer Integer) . Integer))
65-
(* . ((Integer Integer) . Integer))
66-
(and . ((Boolean Boolean) . Boolean))
67-
(or . ((Boolean Boolean) . Boolean))
68-
(eq? . ((Integer Integer) . Boolean))))
69-
(define unary-ops
70-
'((- . ((Integer) . Integer))
71-
(not . ((Boolean) . Boolean))))
72-
(define nullary-ops
73-
'((read . (() . Integer))))
74-
(define (check op ts table)
75-
(let ([pts (car (cdr (assq op table)))]
76-
[ret (cdr (cdr (assq op table)))])
77-
(unless (equal? ts pts)
78-
(error "argument type does not match parameter type"
79-
(list ts pts)))
80-
ret))
81-
(define t-ret
82-
(cond
83-
[(eq? 2 (length ts)) (check op ts binary-ops)]
84-
[(eq? 1 (length ts)) (check op ts unary-ops)]
85-
[else (check op ts nullary-ops)]))
99+
(define t-ret (type-check-op op ts))
86100
(values `(has-type (,op ,@new-es) ,t-ret) t-ret)]
87101
[else
88102
(error "type-check couldn't match" e)])))
@@ -136,19 +150,21 @@
136150
body-ss))]
137151
[`(not ,cnd) #:when optimize-if
138152
((flatten-if new-els els-ss new-thn thn-ss) cnd)]
139-
[`(eq? ,e1 ,e2) #:when optimize-if
153+
[`(,cmp ,e1 ,e2)
154+
#:when (and optimize-if (set-member? (comparison-ops) cmp))
140155
(define-values (new-e1 e1-ss) ((flatten #t) e1))
141156
(define-values (new-e2 e2-ss) ((flatten #t) e2))
142157
(define tmp (gensym 'if))
143158
(define thn-ret `(assign ,tmp ,new-thn))
144159
(define els-ret `(assign ,tmp ,new-els))
145160
(values `(has-type ,tmp ,t)
146161
(append e1-ss e2-ss
147-
`((if (eq? ,new-e1 ,new-e2)
162+
`((if (,cmp ,new-e1 ,new-e2)
148163
,(append thn-ss (list thn-ret))
149164
,(append els-ss (list els-ret))))))]
150165
[else
151-
(let-values ([(new-cnd cnd-ss) ((flatten #t) `(has-type ,cnd ,t))])
166+
(let-values ([(new-cnd cnd-ss)
167+
((flatten #t) `(has-type ,cnd ,t))])
152168
(define tmp (gensym 'if))
153169
(define thn-ret `(assign ,tmp ,new-thn))
154170
(define els-ret `(assign ,tmp ,new-els))
@@ -207,19 +223,21 @@
207223
[`(program ,e)
208224
(define-values (new-e ss) ((flatten #t) e))
209225
(define xs (append* (map (collect-locals) ss)))
210-
`(program ,(remove-duplicates xs) ,@(append ss `((return ,new-e))))]
226+
`(program ,(remove-duplicates xs)
227+
,@(append ss `((return ,new-e))))]
211228
[`(program (type ,ty) ,e)
212229
(define-values (new-e ss) ((flatten #t) e))
213230
(define xs (append* (map (collect-locals) ss)))
214-
`(program ,(remove-duplicates xs) (type ,ty) ,@(append ss `((return ,new-e))))]
231+
`(program ,(remove-duplicates xs) (type ,ty)
232+
,@(append ss `((return ,new-e))))]
215233
[else ((super flatten need-atomic) e)])))
216234

217235
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
218236
;; select-instructions : env -> S1 -> S1
219237

220238
(define/override (instructions)
221239
(set-union (super instructions)
222-
(set 'cmpq 'sete 'andq 'orq 'xorq 'notq 'movzbq)))
240+
(set 'cmpq 'set 'andq 'orq 'xorq 'notq 'movzbq)))
223241

224242
(define/override (binary-op->inst op)
225243
(match op
@@ -233,6 +251,17 @@
233251
[`(int ,n) #t]
234252
[else #f]))
235253

254+
(define/public (compare->cc cmp)
255+
(match cmp
256+
['eq? 'e]
257+
['< 'l]
258+
['<= 'le]
259+
['> 'g]
260+
['>= 'ge]
261+
[else (error 'compare->cc "unmatched ~a" cmp)]
262+
))
263+
264+
236265
(define/override (select-instructions)
237266
(lambda (e)
238267
(match e
@@ -252,7 +281,8 @@
252281
`((xorq (int 1) ,new-lhs))]
253282
[else `((movq ,new-e ,new-lhs)
254283
(xorq (int 1) ,new-lhs))])]
255-
[`(assign ,lhs (eq? ,e1 ,e2))
284+
[`(assign ,lhs (,cmp ,e1 ,e2))
285+
#:when (set-member? (comparison-ops) cmp)
256286
(define new-lhs ((select-instructions) lhs))
257287
(define new-e1 ((select-instructions) e1))
258288
(define new-e2 ((select-instructions) e2))
@@ -267,7 +297,7 @@
267297
`((cmpq ,new-e1 ,new-e2))]))
268298
;; This works because movzbq %al, %rax is a valid instruction
269299
(append comparison
270-
`((sete (byte-reg al))
300+
`((set ,(compare->cc cmp) (byte-reg al))
271301
(movzbq (byte-reg al) ,new-lhs))
272302
)]
273303
;; Keep the if statement to simplify register allocation
@@ -306,7 +336,7 @@
306336
[(or `(andq ,s ,d) `(orq ,s ,d) `(xorq ,s ,d))
307337
(set-union (free-vars s) (free-vars d))]
308338
[`(notq ,d) (free-vars d)]
309-
[`(sete ,d) (set)]
339+
[`(set ,cc ,d) (set)]
310340
[else (super read-vars instr)]))
311341

312342
(define/override (write-vars instr)
@@ -316,7 +346,7 @@
316346
[(or `(andq ,s ,d) `(orq ,s ,d) `(xorq ,s ,d))
317347
(free-vars d)]
318348
[`(notq ,d) (free-vars d)]
319-
[`(sete ,d) (free-vars d)]
349+
[`(set ,cc ,d) (free-vars d)]
320350
[else (super write-vars instr)]))
321351

322352
(define/override (uncover-live live-after)
@@ -332,7 +362,8 @@
332362
[else (car thn-lives)]))
333363
(define live-after-els (cond [(null? els-lives) live-after]
334364
[else (car els-lives)]))
335-
(values `(if ,cnd ,new-thn-ss ,(cdr thn-lives) ,new-els-ss ,(cdr els-lives))
365+
(values `(if ,cnd ,new-thn-ss ,(cdr thn-lives)
366+
,new-els-ss ,(cdr els-lives))
336367
(set-union live-after-thn live-after-els
337368
(free-vars cnd)))]
338369
[else ((super uncover-live live-after) ast)]
@@ -365,9 +396,12 @@
365396
(define/override (assign-homes homes)
366397
(lambda (e)
367398
(match e
399+
;; condition codes, bit of a hack here.
400+
['e 'e] ['l 'l] ['le 'le] ['g 'g] ['ge 'ge]
368401
[`(byte-reg ,r) `(byte-reg ,r)]
369-
[`(eq? ,e1 ,e2) `(eq? ,((assign-homes homes) e1)
370-
,((assign-homes homes) e2))]
402+
[`(,cmp ,e1 ,e2) #:when (set-member? (comparison-ops) cmp)
403+
`(,cmp ,((assign-homes homes) e1)
404+
,((assign-homes homes) e2))]
371405
[`(if ,cnd ,thn-ss ,els-ss)
372406
(let ([cnd ((assign-homes homes) cnd)]
373407
[thn-ss (map (assign-homes homes) thn-ss)]
@@ -400,13 +434,14 @@
400434
[`(deref ,r ,n) `(deref ,r ,n)]
401435
[`(int ,n) `(int ,n)]
402436
[`(reg ,r) `(reg ,r)]
403-
[`(if (eq? ,a1 ,a2) ,thn-ss ,els-ss)
437+
[`(if (,cmp ,a1 ,a2) ,thn-ss ,els-ss)
404438
(let ([thn-ss (append* (map (lower-conditionals) thn-ss))]
405439
[els-ss (append* (map (lower-conditionals) els-ss))]
406440
[thn-label (gensym 'then)]
407441
[end-label (gensym 'if_end)])
408442
(append `((cmpq ,a1 ,a2))
409-
`((je ,thn-label)) els-ss `((jmp ,end-label))
443+
`((jmp-if ,(compare->cc cmp) ,thn-label))
444+
els-ss `((jmp ,end-label))
410445
`((label ,thn-label)) thn-ss `((label ,end-label))
411446
))]
412447
[`(callq ,f) `((callq ,f))]
@@ -424,7 +459,7 @@
424459
(define (mem? x) (in-memory? x))
425460
(lambda (e)
426461
(match e
427-
[`(je ,label) `((je ,label))]
462+
[`(jmp-if ,cc ,label) `((jmp-if ,cc ,label))]
428463
[`(jmp ,label) `((jmp ,label))]
429464
[`(label ,label) `((label ,label))]
430465
[`(cmpq ,a1 ,a2)
@@ -455,11 +490,11 @@
455490
(lambda (e)
456491
(match e
457492
[`(byte-reg ,r) (format "%~a" r)]
458-
[`(sete ,d) (format "\tsete\t~a\n" ((print-x86) d))]
493+
[`(set ,cc ,d) (format "\tset~a\t~a\n" cc ((print-x86) d))]
459494
[`(cmpq ,s1 ,s2)
460495
(format "\tcmpq\t~a, ~a\n" ((print-x86) s1)
461496
((print-x86) s2))]
462-
[`(je ,label) (format "\tje ~a\n" label)]
497+
[`(jmp-if ,cc ,label) (format "\tj~a ~a\n" cc label)]
463498
[`(jmp ,label) (format "\tjmp ~a\n" label)]
464499
[`(label ,l) (format "~a:\n" l)]
465500
[`(program ,spill-space (type ,ty) ,ss ...)

dynamic-typing.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@
229229
`((movq ,new-e ,new-lhs)
230230
(andq (int ,any-mask) ,new-lhs)
231231
(cmpq (int ,(pred->tag pred)) ,new-lhs)
232-
(sete (byte-reg al))
232+
(set e (byte-reg al))
233233
(movzbq (byte-reg al) ,new-lhs))]
234234
[else ((super select-instructions) e)]
235235
)))

interp.rkt

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@
183183
['eq? (lambda (v1 v2)
184184
(cond [(and (fixnum? v1) (fixnum? v2)) (eq? v1 v2)]
185185
[(and (boolean? v1) (boolean? v2)) (eq? v1 v2)]))]
186+
['< (lambda (v1 v2)
187+
(cond [(and (fixnum? v1) (fixnum? v2)) (< v1 v2)]))]
188+
['<= (lambda (v1 v2)
189+
(cond [(and (fixnum? v1) (fixnum? v2)) (<= v1 v2)]))]
190+
['> (lambda (v1 v2)
191+
(cond [(and (fixnum? v1) (fixnum? v2)) (> v1 v2)]))]
192+
['>= (lambda (v1 v2)
193+
(cond [(and (fixnum? v1) (fixnum? v2)) (>= v1 v2)]))]
186194
['not (lambda (v) (match v [#t #f] [#f #t]))]
187195
['and (lambda (v1 v2)
188196
(cond [(and (boolean? v1) (boolean? v2))
@@ -269,21 +277,54 @@
269277
[`(eq? ,e1 ,e2)
270278
(if (eq? ((interp-x86-exp env) e1)
271279
((interp-x86-exp env) e2))
272-
1
273-
0)]
280+
1 0)]
281+
[`(< ,e1 ,e2)
282+
(if (< ((interp-x86-exp env) e1)
283+
((interp-x86-exp env) e2))
284+
1 0)]
285+
[`(<= ,e1 ,e2)
286+
(if (<= ((interp-x86-exp env) e1)
287+
((interp-x86-exp env) e2))
288+
1 0)]
289+
[`(> ,e1 ,e2)
290+
(if (> ((interp-x86-exp env) e1)
291+
((interp-x86-exp env) e2))
292+
1 0)]
293+
[`(>= ,e1 ,e2)
294+
(if (>= ((interp-x86-exp env) e1)
295+
((interp-x86-exp env) e2))
296+
1 0)]
274297
[else ((super interp-x86-exp env) ast)]
275298
)))
299+
300+
(define (eflags-status env cc)
301+
(match cc
302+
['e
303+
(define eflags ((interp-x86-exp env) '(reg __flag)))
304+
(arithmetic-shift (bitwise-and eflags #b1000000) -6)]
305+
['l
306+
;; Get the value of the lt flag which doesn't actually exist
307+
;; the lt flag is simulated by overflow == sign for x86
308+
(define eflags ((interp-x86-exp env) '(reg __flag)))
309+
(define overflow (bitwise-and eflags #b100000000000))
310+
(define sign (bitwise-and eflags #b000010000000))
311+
(if (= overflow sign) 1 0)]
312+
['le
313+
(or (eflags-status env 'e) (eflags-status env 'l))]
314+
['g
315+
(not (eflags-status env 'le))]
316+
['ge
317+
(not (eflags-status env 'l))]))
276318

277319
(define/override (interp-x86 env)
278320
(lambda (ast)
279321
(when (pair? ast)
280322
(vomit "R1/interp-x86" (car ast) env))
281323
(match ast
282-
[`((sete ,d) . ,ss)
283-
(define eflags ((interp-x86-exp env) '(reg __flag)))
284-
(define zero (arithmetic-shift (bitwise-and eflags #b1000000) -6))
324+
[`((set ,cc ,d) . ,ss)
285325
(define name (get-name d))
286-
((interp-x86 (cons (cons name zero) env)) ss)]
326+
(define val (eflags-status env cc))
327+
((interp-x86 (cons (cons name val) env)) ss)]
287328
;; if's are present before patch-instructions
288329
[(or `((if ,cnd ,thn ,els) . ,ss)
289330
`((if ,cnd ,thn ,_ ,els ,_) . ,ss))
@@ -305,14 +346,13 @@
305346
((interp-x86 (cons (cons x v) env)) ss)]
306347
[`((jmp ,label) . ,ss)
307348
((interp-x86 env) (goto-label label (program)))]
308-
[`((je ,label) . ,ss)
349+
[`((jmp-if e ,label) . ,ss)
309350
(let* ([eflags (lookup '__flag env)]
310351
[zero (bitwise-and #b1000000 eflags)]
311352
[zero? (i2b (arithmetic-shift zero -6))])
312353
(cond [zero?
313354
((interp-x86 env) (goto-label label (program)))]
314355
[else ((interp-x86 env) ss)]))]
315-
316356
[`(program ,xs (type ,ty) ,ss ...)
317357
(display-by-type ty ((interp-x86 env) `(program ,xs ,@ss)) env)]
318358
[`(program ,xs ,ss ...)
@@ -585,15 +625,6 @@
585625
(when (pair? ast)
586626
(vomit "R2/interp-x86" (car ast) env))
587627
(match ast
588-
;; Get the value of the lt flag which doesn't actually exist
589-
;; the lt flag is simulated by overflow == sign for x86
590-
[`((setl ,d) . ,ss)
591-
(define eflags ((interp-x86-exp env) '(reg __flag)))
592-
(define overflow (bitwise-and eflags #b100000000000))
593-
(define sign (bitwise-and eflags #b000010000000))
594-
(define lt (if (= overflow sign) 1 0))
595-
(define new-env ((interp-x86-store env) d lt))
596-
((interp-x86 new-env) ss)]
597628
;; cmpq performs a subq operation and examimines the state
598629
;; of the result, this is done without overiting the second
599630
;; register. -andre

0 commit comments

Comments
 (0)