#lang typed/racket/base (require "assemble-structs.rkt" "collect-jump-targets.rkt" "../compiler/il-structs.rkt" "../compiler/expression-structs.rkt" "../parameters.rkt" racket/list) ;; Breaks up a sequence of statements into a list of basic blocks. ;; ;; The first basic block is special, and represents the start of execution. ;; ;; A basic block consists of a sequence of straight line statements, followed by one of ;; the following: ;; ;; * A conditional jump. ;; * An unconditional jump. ;; * Termination. (provide fracture) ;; fracture: (listof stmt) -> (listof basic-block) (: fracture ((Listof Statement) -> (values (Listof BasicBlock) (Listof Symbol)))) (define (fracture stmts) (define start-time (current-inexact-milliseconds)) (define-values (blocks entries) (let*: ([first-block-label : Symbol (if (and (not (empty? stmts)) (symbol? (first stmts))) (first stmts) (make-label 'start))] [stmts : (Listof Statement) (if (and (not (empty? stmts)) (symbol? (first stmts))) (rest stmts) stmts)] [jump-targets : (Listof Symbol) (cons first-block-label (collect-general-jump-targets stmts))] [entry-points : (Listof Symbol) (cons first-block-label (collect-entry-points stmts))]) (define jump-targets-ht ((inst make-hasheq Symbol Boolean))) (for ([name jump-targets]) (hash-set! jump-targets-ht name #t)) (set! start-time (current-inexact-milliseconds)) (let: loop : (values (Listof BasicBlock) (Listof Symbol)) ([name : Symbol first-block-label] [acc : (Listof UnlabeledStatement) '()] [basic-blocks : (Listof BasicBlock) '()] [stmts : (Listof Statement) stmts] [last-stmt-goto? : Boolean #f]) (cond [(null? stmts) (values (reverse (cons (make-BasicBlock name (reverse acc)) basic-blocks)) entry-points)] [else (let: ([first-stmt : Statement (car stmts)]) (: do-on-label (Symbol -> (values (Listof BasicBlock) (Listof Symbol)))) (define (do-on-label label-name) (cond [(hash-has-key? jump-targets-ht label-name) (loop label-name '() (cons (make-BasicBlock name (if last-stmt-goto? (reverse acc) (reverse (cons (make-Goto (make-Label label-name)) acc)))) basic-blocks) (cdr stmts) last-stmt-goto?)] [else (loop name acc basic-blocks (cdr stmts) last-stmt-goto?)])) (cond [(symbol? first-stmt) (do-on-label first-stmt)] [(LinkedLabel? first-stmt) (do-on-label (LinkedLabel-label first-stmt))] [else (loop name (cons first-stmt acc) basic-blocks (cdr stmts) (Goto? (car stmts)))]))])))) (define end-time (current-inexact-milliseconds)) (fprintf (current-timing-port) " assemble fracture: ~a milliseconds\n" (- end-time start-time)) (values blocks entries))