Web page for IU Compiler Course for Fall 2020
View the Project on GitHub IUCompilerCourse/IU-P423-P523-E313-E513-Fall-2020
Announcements:
type-checkHasTypevector-set!(define (type-check-exp env e)
  (match e
    [(Var x)
     (define type (match-alist x env))
     (values (HasType (Var x) type) type)]
    ...
    [(Prim 'vector-set! (list vect (Int i) val))
     (define-values (vect-exp vect-type) (type-check-exp env vect))
     (define-values (i-exp i-type) (type-check-exp env (Int i)))
     (define-values (val-exp val-type) (type-check-exp env val))
     (if (not (eq? i-type 'Integer))
         (error "The type of index for vector-set! must be an Integer")
         (if (not (eq? (car vect-type) 'Vector))
             (error "Vector set got a non vector")
             (if (not (equal? (list-ref vect-type (add1 i)) val-type))
                 (error (format "Changing vector types is not supported got ~a ~a" 
                     (list-ref vect-type (add1 i)) val-type))
                 (values (HasType (Prim 'vector-set! (list vect-exp i-exp val-exp))
                                  'Void) 'Void))))]
    ...)
expose-allocationlower (vector e1 ... en) creation into:
e1 … encollect if there is not enough room in the FromSpaceallocate formvector-set!(define (expose-exp e)
  (match e
    [(HasType (Prim 'vector es) type)
     (let* ([len (length es)] 
            [bytes (* 8 len)]
            [vect (gensym 'vec)] 
            [vars (generate-n-vars len)])
       (expand-into-lets vars (for/list ([e es]) (expose-exp e)) 
          (do-allocate vect len bytes
              (bulk-vector-set (HasType (Var vect) type) vars type) 
              type)
          type))]
    ...))
;; for/list, range
(define (generate-n-vars n)
  (if (zero? n) '()
      (cons (gensym 'tmp) (generate-n-vars (sub1 n)))))
(define (expand-into-lets vars exps base base-type)
  (if (empty? exps) base
    (HasType
      (Let (car vars) (car exps) 
           (expand-into-lets (cdr vars) (cdr exps) base base-type))
      base-type)))
;; ommitting the HasType's for readability
(define (do-allocate vect len bytes base type)
    (Let '_ (If (Prim '< (list (Prim '+ (list (GlobalValue 'free_ptr) (Int bytes)))
                                 (GlobalValue 'fromspace_end)))
                (Void)
                (Collect bytes))
    (Let vect (Allocate len type) base)))
(define (bulk-vector-set vect vars types)
  (expand-into-lets (duplicate '_ (length vars)) 
    (make-vector-set-exps vect 0 vars (cdr types)) vect types))
;; use Racket's make-list instead, for/list
(define (duplicate x n) 
  (if (zero? n) '()
      (cons x (duplicate x (sub1 n)))))
;; for/list
(define (make-vector-set-exps vect accum vars types)
  (if (empty? vars) '()
      (cons (Prim 'vector-set! (list vect (Int accum) (Var (car vars))))
            (make-vector-set-exps vect (add1 accum) (cdr vars) (cdr types)))))
uncover-localsCollect up all the variables and their types into an association list
in the Program info.
(define (uncover-block tail)
  (match tail
    [(Seq (Assign var (HasType x type)) t)
     (cons `(,var . ,type) (uncover-block t))]
    [x '()]))
(define (uncover-locals p)
  (match p
    [(Program info (CFG B-list))
     (let ([locals (remove-duplicates
                     (append-map (lambda (x) 
                                    (uncover-block (cdr x))) B-list))])
       (Program `((locals . ,locals)) (CFG B-list)))]))
select-instructionsLower each of the following forms to x86:
vector-refvector-set!allocatecollect(define (slct-stmt tail)
  (match tail
    [(Assign (Var x) (HasType exp t))
     (match exp
       ...
       [(Prim 'vector-ref (list (HasType vect t1) (HasType (Int n) t2))) 
        (list (Instr 'movq (list (slct-atom vect) (Reg 'r11))) 
              (Instr 'movq (list (Deref 'r11 (* 8 (add1 n))) (Var x))))]
       [(Prim 'vector-set! (list (HasType vect t1) (HasType (Int n) t2) (HasType arg t3)))
        (list (Instr 'movq (list (slct-atom vect) (Reg 'r11))) 
              (Instr 'movq (list (slct-atom arg) (Deref 'r11 (* 8 (add1 n))))) 
              (Instr 'movq (list (Imm 0) (Var x))))]
       [(Allocate len types)
        (let ([tag (calculate-tag (reverse (cdr types)) (length (cdr types)))])
          (list (Instr 'movq (list (Global 'free_ptr) (Var x))) 
                (Instr 'addq (list (Imm (* 8 (add1 len))) (Global 'free_ptr))) 
                (Instr 'movq (list (Var x) (Reg 'r11))) 
                (Instr 'movq (list (Imm tag) (Deref 'r11 0)))))]
       [(Collect bytes) 
        (list (Instr 'movq (list (Reg 'r15) (Reg 'rdi)))
              (Instr 'movq (list (Imm bytes) (Reg 'rsi))) 
              (Callq 'collect))]
       ...)]))
build-interferenceVariables of vector type that are live during a call to collect must
be spilled. To ensure that, create interference edges with
callee-saved registers.  (We already add edges to the caller-saved
registers.)
(define (add-from-instr graph instr live-after types)
  (match instr
    [(Callq 'collect)
     (for ([x live-after]) 
       (if (list? (match-alist (Var x) types))  ;; is variable x a vector?, vector-type?
         (for ([y (append caller-registers callee-registers)])
           (add-edge! graph x y))
         (for ([y caller-registers]) 
           (add-edge! graph x y))))]
    ...))
allocate-registersSpill vector-typed variables to the root stack.
2 root stack spills 3 regular spills
How much space on root stack? 5 slots On the regular stack? 5 slots
Two registers: 0 int 1 int —— 2 vector 0 3 int 1 4 int 2 5 vector 3 6 int 4
(define (assign-nat n type)
  (let [(last-reg (sub1 (length reg-colors)))]
    (cond [(<= n last-reg)
           (Reg (rev-match-alist n reg-colors))]
          [(list? type) ;; vector-type?
           (Deref 'r15 (* 8 (add1 (- n last-reg))))]
          [else
           (Deref 'rbp (* (add1 (- n last-reg)) (- 8)))]
          )))
(define (generate-assignments locals colors)
  (cond [(empty? locals) '()]
        [else (match (car locals)
                [`(,(Var v) . ,type)
                 (cons `(,v . ,(assign-nat (match-alist v colors) type)) 
                       (generate-assignments (cdr locals) colors))])]))
print-x86In the prelude, call the initialize function to set up the garbage
collector.
In the prelude and conclusion, add code for pushing and popping a
frame for main to the root stack. Initialize all the slots in the
frame to zero.
(define (make-main stack-size used-regs root-spills)
  (let* ([extra-pushes (filter (lambda (reg)
                                (match reg
                                  [(Reg x) (index-of callee-registers x)]
                                  [x false]))
                              used-regs)]
         [push-bytes (* 8 (length extra-pushes))]
         [stack-adjust (- (round-stack-to-16 (+ push-bytes stack-size)) push-bytes)])
    (Block '()
      (append (list (Instr 'pushq (list (Reg 'rbp)))
                    (Instr 'movq (list (Reg 'rsp) (Reg 'rbp))))
              (map (lambda (x) (Instr 'pushq (list x))) extra-pushes) 
              (list (Instr 'subq (list (Imm stack-adjust) (Reg 'rsp)))) 
              (initialize-garbage-collector root-spills)
              (list (Jmp 'start))))))
(define (initialize-garbage-collector root-spills)
  (list (Instr 'movq (list (Imm root-stack-size) (Reg 'rdi)))
        (Instr 'movq (list (Imm heap-size) (Reg 'rsi)))
        (Callq 'initialize)
        (Instr 'movq (list (Global 'rootstack_begin) (Reg 'r15)))
        (Instr 'movq (list (Imm 0) (Deref (Reg 'r15) 0))
        ...
        (Instr 'movq (list (Imm 0) (Deref (Reg 'r15) k))
        (Instr 'addq (list (Imm root-spills) (Reg 'r15)))))