1 ;;; generation of control flow graph
22 extender: define-type-of-instr
23 (live-before #;unprintable:)
24 (live-after #;unprintable:)
32 (define-type-of-instr call-instr
37 (define-type-of-instr return-instr
42 (define (new-instr id src1 src2 dst)
43 (make-instr '() '() #f id src1 src2 dst))
45 (define (new-call-instr def-proc)
46 (make-call-instr '() '() #f 'call #f #f #f def-proc))
48 (define (new-return-instr def-proc)
49 (make-return-instr '() '() #f 'return #f #f #f def-proc))
52 (let* ((label-num (cfg-next-label-num cfg))
53 (bb (make-bb label-num #f '() '() '() '())))
59 (number->string label-num)))))
60 (cfg-bbs-set! cfg (cons bb (cfg-bbs cfg)))
61 (cfg-next-label-num-set! cfg (+ 1 (cfg-next-label-num cfg)))
64 (define (add-instr bb instr)
65 (let ((rev-instrs (bb-rev-instrs bb)))
66 (bb-rev-instrs-set! bb (cons instr rev-instrs))))
68 (define (add-succ bb succ)
69 (bb-succs-set! bb (cons succ (bb-succs bb)))
70 (bb-preds-set! succ (cons bb (bb-preds succ))))
72 (define (generate-cfg ast)
74 (define cfg (new-cfg))
76 (define bb #f) ; current bb
87 (define current-def-proc #f)
88 (define break-stack '())
89 (define continue-stack '())
90 (define delayed-post-incdec '())
92 (define (push-break x)
93 (set! break-stack (cons x break-stack)))
96 (set! break-stack (cdr break-stack)))
98 (define (push-continue x)
99 (set! continue-stack (cons x continue-stack)))
101 (define (pop-continue)
102 (set! continue-stack (cdr continue-stack)))
104 (define (push-delayed-post-incdec x)
105 (set! delayed-post-incdec (cons x delayed-post-incdec)))
107 (define (program ast)
108 (let loop ((asts (ast-subasts ast)))
109 (if (not (null? asts))
110 (let ((ast (car asts)))
111 (if (null? (cdr asts))
112 (let ((value (expression ast)))
113 (return-with-no-new-bb value))
116 (loop (cdr asts))))))))
118 (define (toplevel ast)
119 (cond ((def-variable? ast)
121 ((def-procedure? ast)
126 (define (def-variable ast)
127 (let ((subasts (ast-subasts ast)))
128 (if (not (null? subasts))
129 (let ((value (expression (subast1 ast))))
130 (let ((ext-value (extend value (def-variable-type ast))))
131 (move-value value (def-variable-value ast)))))))
133 (define (def-procedure ast)
136 (def-procedure-entry-set! ast entry)
137 (set! current-def-proc ast)
139 (for-each statement (ast-subasts ast))
140 (return-with-no-new-bb ast)
141 (set! current-def-proc #f)
144 (define (statement ast) ;; TODO should labels go into statements or expressions ?
145 (cond ((def-variable? ast)
152 (if (null? (cddr (ast-subasts ast)))
165 (for-each statement (ast-subasts ast)))
167 (define (move from to)
168 (emit (new-instr 'move from #f to)))
170 (define (move-value from to)
175 (define (return-with-no-new-bb def-proc)
176 (emit (new-return-instr def-proc)))
179 (if (null? (ast-subasts ast))
180 (return-with-no-new-bb current-def-proc)
181 (let ((value (expression (subast1 ast))))
182 (let ((ext-value (extend value (def-procedure-type current-def-proc))))
183 (move-value value (def-procedure-value current-def-proc))
184 (return-with-no-new-bb current-def-proc))))
188 (let* ((bb-join (new-bb))
190 (test-expression (subast1 ast) bb-then bb-join)
192 (statement (subast2 ast))
196 (let* ((bb-join (new-bb))
199 (test-expression (subast1 ast) bb-then bb-else)
201 (statement (subast2 ast))
204 (statement (subast3 ast))
209 (let* ((bb-cont (new-bb))
212 (push-continue bb-cont)
216 (test-expression (subast1 ast) bb-body bb-exit)
218 (statement (subast2 ast))
224 (define (do-while ast)
225 (let* ((bb-body (new-bb))
228 (push-continue bb-cont)
231 (statement (subast1 ast))
233 (test-expression (subast2 ast) bb-body bb-exit)
239 (let* ((bb-loop (new-bb))
243 (statement (subast1 ast))
245 (push-continue bb-cont)
248 (test-expression (subast2 ast) bb-body bb-exit)
250 (statement (subast4 ast))
253 (expression (subast3 ast))
261 (emit (new-instr 'goto #f #f #f)))
263 (define (test-expression ast bb-true bb-false)
265 (define (test-lit id x y)
270 (else (error "...")))
274 (define (test-byte id byte1 byte2 bb-true bb-false)
275 (cond ((and (byte-lit? byte1) (byte-lit? byte2))
276 (if (test-lit id (byte-lit-val byte1) (byte-lit-val byte2))
280 (add-succ bb bb-true)
281 (add-succ bb bb-false)
282 (emit (new-instr id byte1 byte2 #f)))
289 (else (error "...")))))
290 (add-succ bb bb-true)
291 (add-succ bb bb-false)
292 (emit (new-instr id byte2 byte1 #f))))
294 (add-succ bb bb-true)
295 (add-succ bb bb-false)
296 (emit (new-instr id byte1 byte2 #f)))))
298 (define (test-value id value1 value2 bb-true bb-false)
299 ; note: for multi-byte values, only x==y works properly
300 (let* ((bytes1 (value-bytes value1))
301 (bytes2 (value-bytes value2)))
302 (let loop ((bytes1 bytes1) (bytes2 bytes2))
303 (let ((byte1 (car bytes1))
304 (byte2 (car bytes2)))
305 (if (null? (cdr bytes1))
306 (test-byte id byte1 byte2 bb-true bb-false)
307 (let ((bb-true2 (new-bb)))
308 (test-byte id byte1 byte2 bb-true2 bb-false)
310 (loop (cdr bytes1) (cdr bytes2))))))))
312 (define (test-relation id x y bb-true bb-false)
313 (cond ((and (literal? x) (not (literal? y)))
320 (else (error "relation error")))
325 ((assq id '((x!=y . x==y) (x<=y . x>y) (x>=y . x<y)))
327 (lambda (z) (compare (cdr z) x y bb-false bb-true)))
332 (cond ((and (literal? y) (= (literal-val y) 0))
333 (test-zero x bb-true bb-false))
335 (test-eq-lit x (literal-val y) bb-true bb-false))
337 (error "unhandled case"))))
339 (cond ((and (literal? y) (= (literal-val y) 0))
340 (test-negative x bb-true bb-false))
342 (error "unhandled case"))))
344 (cond ((and (literal? y) (= (literal-val y) 0))
345 (test-positive x bb-true bb-false))
347 (error "unhandled case"))))
349 (error "unexpected operator")))
351 (let* ((value1 (expression x))
352 (value2 (expression y)))
353 (test-value id value1 value2 bb-true bb-false))
356 (define (test-zero ast bb-true bb-false)
359 (let ((type (expr-type ast))
360 (value (expression ast)))
361 (test-equal value (int->value 0 type) bb-true bb-false)))
364 (let* ((op (oper-op ast))
368 (test-zero (subast1 ast) bb-false bb-true))
382 (test-zero ast bb-false bb-true))
384 (define (expression ast)
386 (cond ((literal? ast)
395 (error "unexpected ast" ast)))))
396 (do-delayed-post-incdec)
399 (define (literal ast)
400 (let ((val (literal-val ast)))
401 (int->value val (expr-type ast))))
404 (let* ((def-var (ref-def-var ast))
405 (value (def-variable-value def-var)))
408 (define (add-sub id value1 value2 result)
409 (let loop ((bytes1 (value-bytes value1))
410 (bytes2 (value-bytes value2))
411 (bytes3 (value-bytes result))
412 (ignore-carry-borrow? #t))
413 (if (not (null? bytes1))
414 (let ((byte1 (car bytes1))
416 (byte3 (car bytes3)))
418 (new-instr (if ignore-carry-borrow?
419 (case id ((x+y) 'add) ((x-y) 'sub))
420 (case id ((x+y) 'addc) ((x-y) 'subb)))
429 (define (do-delayed-post-incdec)
430 (if (not (null? delayed-post-incdec))
431 (let* ((ast (car delayed-post-incdec))
432 (type (expr-type ast))
435 (set! delayed-post-incdec (cdr delayed-post-incdec))
436 (let ((x (subast1 ast)))
438 (error "assignment target must be a variable"))
439 (let ((result (def-variable-value (ref-def-var x))))
440 (add-sub (if (eq? id 'x++) 'x+y 'x-y)
444 (do-delayed-post-incdec))))
447 (let* ((type (expr-type ast))
450 (let ((op (oper-op ast)))
455 (let ((x (subast1 ast)))
456 (let ((value-x (expression x)))
457 (let ((ext-value-x (extend value-x type)))
458 (let ((result (alloc-value type)))
465 (let ((x (subast1 ast)))
467 (error "assignment target must be a variable"))
468 (let ((result (def-variable-value (ref-def-var x))))
469 (add-sub (if (eq? id '++x) 'x+y 'x-y)
475 (let ((x (subast1 ast)))
477 (error "assignment target must be a variable"))
478 (let ((result (def-variable-value (ref-def-var x))))
479 (push-delayed-post-incdec ast)
482 (error "unary operation error" ast))))
485 ((x+y x-y x*y x/y x%y)
486 (let* ((x (subast1 ast))
488 (let* ((value-x (expression x))
489 (value-y (expression y)))
490 (let* ((ext-value-x (extend value-x type))
491 (ext-value-y (extend value-y type)))
492 (let ((result (alloc-value type)))
493 (if (or (eq? id 'x+y)
495 (add-sub id ext-value-x ext-value-y result)
499 (let* ((x (subast1 ast))
502 (error "assignment target must be a variable"))
503 (let ((value-y (expression y)))
504 (let ((ext-value-y (extend value-y type)))
505 (let ((result (def-variable-value (ref-def-var x))))
506 (move-value value-y result)
509 (error "binary operation error" ast))))))))
512 (let ((def-proc (call-def-proc ast)))
513 (for-each (lambda (ast def-var)
514 (let ((value (expression ast)))
515 (let ((ext-value (extend value (def-variable-type def-var))))
516 (move-value value (def-variable-value def-var)))))
518 (def-procedure-params def-proc))
519 (emit (new-call-instr def-proc))
520 (let ((value (def-procedure-value def-proc)))
521 (let ((result (alloc-value (def-procedure-type def-proc))))
522 (move-value value result)