|
12 | 12 |
|
13 | 13 | (inherit liveness-ss first-offset variable-size in-memory?)
|
14 | 14 |
|
| 15 | + (define/public (comparison-ops) |
| 16 | + (set 'eq? '< '<= '> '>=)) |
| 17 | + |
15 | 18 | (define/override (primitives)
|
16 | 19 | (set-union (super primitives)
|
17 |
| - (set 'eq? 'and 'or 'not))) |
| 20 | + (comparison-ops) |
| 21 | + (set 'and 'or 'not))) |
18 | 22 |
|
19 | 23 | (define/public (insert-type-node node ty)
|
20 | 24 | (match node
|
|
24 | 28 |
|
25 | 29 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
26 | 30 | ;; 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 | + |
27 | 64 | (define/public (type-check env)
|
28 | 65 | (lambda (e)
|
29 | 66 | (vomit "conditionals/type-check" e env)
|
|
59 | 96 | [`(,op ,es ...) #:when (set-member? (primitives) op)
|
60 | 97 | (define-values (new-es ts)
|
61 | 98 | (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)) |
86 | 100 | (values `(has-type (,op ,@new-es) ,t-ret) t-ret)]
|
87 | 101 | [else
|
88 | 102 | (error "type-check couldn't match" e)])))
|
|
136 | 150 | body-ss))]
|
137 | 151 | [`(not ,cnd) #:when optimize-if
|
138 | 152 | ((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)) |
140 | 155 | (define-values (new-e1 e1-ss) ((flatten #t) e1))
|
141 | 156 | (define-values (new-e2 e2-ss) ((flatten #t) e2))
|
142 | 157 | (define tmp (gensym 'if))
|
143 | 158 | (define thn-ret `(assign ,tmp ,new-thn))
|
144 | 159 | (define els-ret `(assign ,tmp ,new-els))
|
145 | 160 | (values `(has-type ,tmp ,t)
|
146 | 161 | (append e1-ss e2-ss
|
147 |
| - `((if (eq? ,new-e1 ,new-e2) |
| 162 | + `((if (,cmp ,new-e1 ,new-e2) |
148 | 163 | ,(append thn-ss (list thn-ret))
|
149 | 164 | ,(append els-ss (list els-ret))))))]
|
150 | 165 | [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))]) |
152 | 168 | (define tmp (gensym 'if))
|
153 | 169 | (define thn-ret `(assign ,tmp ,new-thn))
|
154 | 170 | (define els-ret `(assign ,tmp ,new-els))
|
|
207 | 223 | [`(program ,e)
|
208 | 224 | (define-values (new-e ss) ((flatten #t) e))
|
209 | 225 | (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))))] |
211 | 228 | [`(program (type ,ty) ,e)
|
212 | 229 | (define-values (new-e ss) ((flatten #t) e))
|
213 | 230 | (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))))] |
215 | 233 | [else ((super flatten need-atomic) e)])))
|
216 | 234 |
|
217 | 235 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
218 | 236 | ;; select-instructions : env -> S1 -> S1
|
219 | 237 |
|
220 | 238 | (define/override (instructions)
|
221 | 239 | (set-union (super instructions)
|
222 |
| - (set 'cmpq 'sete 'andq 'orq 'xorq 'notq 'movzbq))) |
| 240 | + (set 'cmpq 'set 'andq 'orq 'xorq 'notq 'movzbq))) |
223 | 241 |
|
224 | 242 | (define/override (binary-op->inst op)
|
225 | 243 | (match op
|
|
233 | 251 | [`(int ,n) #t]
|
234 | 252 | [else #f]))
|
235 | 253 |
|
| 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 | + |
236 | 265 | (define/override (select-instructions)
|
237 | 266 | (lambda (e)
|
238 | 267 | (match e
|
|
252 | 281 | `((xorq (int 1) ,new-lhs))]
|
253 | 282 | [else `((movq ,new-e ,new-lhs)
|
254 | 283 | (xorq (int 1) ,new-lhs))])]
|
255 |
| - [`(assign ,lhs (eq? ,e1 ,e2)) |
| 284 | + [`(assign ,lhs (,cmp ,e1 ,e2)) |
| 285 | + #:when (set-member? (comparison-ops) cmp) |
256 | 286 | (define new-lhs ((select-instructions) lhs))
|
257 | 287 | (define new-e1 ((select-instructions) e1))
|
258 | 288 | (define new-e2 ((select-instructions) e2))
|
|
267 | 297 | `((cmpq ,new-e1 ,new-e2))]))
|
268 | 298 | ;; This works because movzbq %al, %rax is a valid instruction
|
269 | 299 | (append comparison
|
270 |
| - `((sete (byte-reg al)) |
| 300 | + `((set ,(compare->cc cmp) (byte-reg al)) |
271 | 301 | (movzbq (byte-reg al) ,new-lhs))
|
272 | 302 | )]
|
273 | 303 | ;; Keep the if statement to simplify register allocation
|
|
306 | 336 | [(or `(andq ,s ,d) `(orq ,s ,d) `(xorq ,s ,d))
|
307 | 337 | (set-union (free-vars s) (free-vars d))]
|
308 | 338 | [`(notq ,d) (free-vars d)]
|
309 |
| - [`(sete ,d) (set)] |
| 339 | + [`(set ,cc ,d) (set)] |
310 | 340 | [else (super read-vars instr)]))
|
311 | 341 |
|
312 | 342 | (define/override (write-vars instr)
|
|
316 | 346 | [(or `(andq ,s ,d) `(orq ,s ,d) `(xorq ,s ,d))
|
317 | 347 | (free-vars d)]
|
318 | 348 | [`(notq ,d) (free-vars d)]
|
319 |
| - [`(sete ,d) (free-vars d)] |
| 349 | + [`(set ,cc ,d) (free-vars d)] |
320 | 350 | [else (super write-vars instr)]))
|
321 | 351 |
|
322 | 352 | (define/override (uncover-live live-after)
|
|
332 | 362 | [else (car thn-lives)]))
|
333 | 363 | (define live-after-els (cond [(null? els-lives) live-after]
|
334 | 364 | [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)) |
336 | 367 | (set-union live-after-thn live-after-els
|
337 | 368 | (free-vars cnd)))]
|
338 | 369 | [else ((super uncover-live live-after) ast)]
|
|
365 | 396 | (define/override (assign-homes homes)
|
366 | 397 | (lambda (e)
|
367 | 398 | (match e
|
| 399 | + ;; condition codes, bit of a hack here. |
| 400 | + ['e 'e] ['l 'l] ['le 'le] ['g 'g] ['ge 'ge] |
368 | 401 | [`(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))] |
371 | 405 | [`(if ,cnd ,thn-ss ,els-ss)
|
372 | 406 | (let ([cnd ((assign-homes homes) cnd)]
|
373 | 407 | [thn-ss (map (assign-homes homes) thn-ss)]
|
|
400 | 434 | [`(deref ,r ,n) `(deref ,r ,n)]
|
401 | 435 | [`(int ,n) `(int ,n)]
|
402 | 436 | [`(reg ,r) `(reg ,r)]
|
403 |
| - [`(if (eq? ,a1 ,a2) ,thn-ss ,els-ss) |
| 437 | + [`(if (,cmp ,a1 ,a2) ,thn-ss ,els-ss) |
404 | 438 | (let ([thn-ss (append* (map (lower-conditionals) thn-ss))]
|
405 | 439 | [els-ss (append* (map (lower-conditionals) els-ss))]
|
406 | 440 | [thn-label (gensym 'then)]
|
407 | 441 | [end-label (gensym 'if_end)])
|
408 | 442 | (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)) |
410 | 445 | `((label ,thn-label)) thn-ss `((label ,end-label))
|
411 | 446 | ))]
|
412 | 447 | [`(callq ,f) `((callq ,f))]
|
|
424 | 459 | (define (mem? x) (in-memory? x))
|
425 | 460 | (lambda (e)
|
426 | 461 | (match e
|
427 |
| - [`(je ,label) `((je ,label))] |
| 462 | + [`(jmp-if ,cc ,label) `((jmp-if ,cc ,label))] |
428 | 463 | [`(jmp ,label) `((jmp ,label))]
|
429 | 464 | [`(label ,label) `((label ,label))]
|
430 | 465 | [`(cmpq ,a1 ,a2)
|
|
455 | 490 | (lambda (e)
|
456 | 491 | (match e
|
457 | 492 | [`(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))] |
459 | 494 | [`(cmpq ,s1 ,s2)
|
460 | 495 | (format "\tcmpq\t~a, ~a\n" ((print-x86) s1)
|
461 | 496 | ((print-x86) s2))]
|
462 |
| - [`(je ,label) (format "\tje ~a\n" label)] |
| 497 | + [`(jmp-if ,cc ,label) (format "\tj~a ~a\n" cc label)] |
463 | 498 | [`(jmp ,label) (format "\tjmp ~a\n" label)]
|
464 | 499 | [`(label ,l) (format "~a:\n" l)]
|
465 | 500 | [`(program ,spill-space (type ,ty) ,ss ...)
|
|
0 commit comments