IU-P423-P523-E313-E513-Fall-2020

Web page for IU Compiler Course for Fall 2020

View the Project on GitHub IUCompilerCourse/IU-P423-P523-E313-E513-Fall-2020

Code Review

uniquify

(define (uniquify-exp symtab)
  (lambda (e)
    (match e
      [(Var x) (Var (get-sym-rep symtab x))] ;; (dict-ref symtab x)
      [(Int n) (Int n)]
      [(Let x e body)
       (let* ([new-sym (gensym x)]
              [new-symtab (add-to-symtab symtab x new-sym)])
              ;; (dict-set symtab x new-sym)
         (Let new-sym  ((uniquify-exp symtab) e)
           ((uniquify-exp new-symtab) body)))]
      [(Prim op es)
       (Prim op (for/list ([e es]) ((uniquify-exp symtab) e)))]
      )))

Example:

(let ([x 10])
   (let ([x (+ x 1)])
     x))

wrong:
(let ([x.1 10])
   (let ([x.2 (+ x.2 1)])
     x.2))
     
correct:
(let ([x.1 10])
   (let ([x.2 (+ x.1 1)])
     x.2))

remove-complex-opera*

;; rco-atom : exp -> exp * (var * exp) list
(define (rco-atom e)
  (match e
    [(Var x) (values (Var x) '())]
    [(Int n) (values (Int n) '())]
    [(Let x rhs body)
     (define new-rhs (rco-exp rhs))
     (define-values (new-body body-ss) (rco-atom body))
     (values new-body (append `((,x . ,new-rhs)) body-ss))]
    [(Prim op es) 
     (define-values (new-es sss)
       (for/lists (l1 l2) ([e es]) (rco-atom e)))
     (define ss (append* sss))
     (define tmp (gensym 'tmp))
     (values (Var tmp)
             (append ss `((,tmp . ,(Prim op new-es)))))]
    ))

(define (make-lets bs e)
  (match bs
    [`() e]
    [`((,x . ,e^) . ,bs^)
     (Let x e^ (make-lets bs^ e))]))

;; rco-exp : exp -> exp
(define (rco-exp e)
  (match e
    [(Var x) (Var x)]
    [(Int n) (Int n)]
    [(Let x rhs body)
     (Let x (rco-exp rhs) (rco-exp body))]
    [(Prim op es)
     (define-values (new-es sss)
       (for/lists (l1 l2) ([e es]) (rco-atom e)))
     (make-lets (append* sss) (Prim op new-es))]
    ))

explicate-control

(define (explicate-tail exp)
  (match exp
    [(Var x) (values (Return (Var x)) '())]
    [(Int n) (values (Return (Int n)) '())]
    [(Let lhs rhs body)
     (let*-values
         ([(body-c0 body-vars) (explicate-tail body)]
          [(new-tail new-rhs-vars) (explicate-assign lhs rhs body-c0)])
       (values new-tail (append new-rhs-vars body-vars)))]
    [(Prim op es)
     (values (Return (Prim op es)) '())]))

(define (explicate-assign r1exp v c)
  (match r1exp
    [(Let x e body) 
     (define-values (tail let-binds) (explicate-assign body v c))
     (define-values (tail^ let-binds^) (explicate-assign e (Var x) tail))
     (values tail^ (cons x (append let-binds let-binds^)))]
    [else
      (values (Seq (Assign v r1exp) c) '())]
     ))

select-instructions

(define (select-instr-atm a)
  (match a
    [(Int i) (Imm i)]
    [(Var _) a]))

(define (select-instr-assign v e)
  (match e
    [(Int i) 
     (list (Instr 'movq (list (select-instr-atm e) v)))]
    [(Var _)
     (list (Instr 'movq (list (select-instr-atm e) v)))]
    [(Prim 'read '())
     (list (Callq 'read_int)
           (Instr 'movq (list (Reg 'rax) v)))]
    [(Prim '- (list a))
     (list (Instr 'movq (list (select-instr-atm a) v))
           (Instr 'negq (list v)))]
    [(Prim '+ (list a1 a2))
     (list (Instr 'movq (list (select-instr-atm a1) v))
           (Instr 'addq (list (select-instr-atm a2) v)))]))

(define (select-instr-stmt stmt)
  (match stmt
    [(Assign (Var v) (Prim '+ (list (Var v1) a2))) #:when (equal? v v1)
     (list (Instr 'addq (list (select-instr-atm a2) (Var v))))]
    [(Assign (Var v) (Prim '+ (list a1 (Var v2)))) #:when (equal? v v2)
     (list (Instr 'addq (list (select-instr-atm a1) (Var v))))]
    [(Assign v e)
     (select-instr-assign v e)]))

(define (select-instr-tail t)
  (match t
    [(Seq stmt t*) 
     (append (select-instr-stmt stmt) (select-instr-tail t*))]
    [(Return (Prim 'read '())) 
     (list (Callq 'read_int) (Jmp 'conclusion))]
    [(Return e) (append
                 (select-instr-assign (Reg 'rax) e)
                 (list (Jmp 'conclusion)))]))

(define (select-instructions p)
  (match p
    [(Program info (CFG (list (cons 'start t))))
     (Program info
       (CFG (list (cons 'start (Block '() (select-instr-tail t))))))]))

assign-homes

(define (calc-stack-space ls) (* 8 (length ls))

(define (find-index v ls)
  (cond
    ;;[(eq? v (Var-name (car ls))) 1]
    [(eq? v (car ls)) 1]
    [else (add1 (find-index v (cdr ls)))]
    ))

(define (assign-homes-imm i ls)
  (match i
    [(Reg reg) (Reg reg)]
    [(Imm int) (Imm int)]
    [(Var v) (Deref 'rbp (* -8 (find-index v (cdr ls))))]
   ))
   
(define (assign-homes-instr i ls)
  (match i
    [(Instr op (list e1)) 
     (Instr op (list (assign-homes-imm e1 ls)))]
    [(Instr op (list e1 e2))
     (Instr op (list (assign-homes-imm e1 ls) (assign-homes-imm e2 ls)))]
    [else i]
    ))
    
(define (assign-homes-block b ls)
  (match b
    [(Block info es) 
     (Block info (for/list ([e es]) (assign-homes-instr e ls)))]
    ))

(define (assign-homes p)
  (match p
    [(Program info (CFG es)) 
     (Program (list (cons 'stack-space (calc-stack-space (cdr (car info)))))
       (CFG (for/list ([ls es]) 
         (cons (car ls) (assign-homes-block (cdr ls) (car info))))))]
    ))

patch-instructions

(define (patch-instr  instruction)
  (match instruction
    [(Instr op (list (Deref  reg off) (Deref reg2 off2)))
         (list (Instr 'movq (list (Deref reg off) (Reg 'rax)))
               (Instr op (list (Reg 'rax) (Deref reg2 off2))))]
    [else (list instruction)]))

(define (patch-block b)
  (match b
    [(Block '() instrs) (Block '() (append-map patch-instr instrs))]
    ))

(define (patch-instructions p)
   (match p
    [(Program info (CFG B-list))
     (Program info
              (CFG
               (map
                (lambda (x) `(,(car x) . ,(patch-block (cdr x)))) 
                B-list)))]))
(define (print-x86-imm e)
  (match e
    [(Deref reg i)
     (format "~a(%~a)" i reg)]
    [(Imm n) (format "$~a" n)]
    [(Reg r) (format "%~a" r)]
    ))

(define (print-x86-instr e)
  (verbose "R1/print-x86-instr" e)
  (match e
    [(Callq f)
     (format "\tcallq\t~a\n" (label-name (symbol->string f)))]
    [(Jmp label) (format "\tjmp ~a\n" (label-name label))]
    [(Instr instr-name (list s d))
     (format "\t~a\t~a, ~a\n" instr-name
             (print-x86-imm s) 
             (print-x86-imm d))]
    [(Instr instr-name (list d))
     (format "\t~a\t~a\n" instr-name (print-x86-imm d))]
    [else (error "R1/print-x86-instr, unmatched" e)]
    ))

(define (print-x86-block e)
  (match e
    [(Block info ss)
     (string-append* (for/list ([s ss]) (print-x86-instr s)))]
    [else
     (error "R1/print-x86-block unhandled " e)]))

(define (print-x86 e)
  (match e
    [(Program info (CFG G))
     (define stack-space (dict-ref info 'stack-space))
     (string-append
      (string-append*
       (for/list ([(label block) (in-dict G)])
         (string-append (format "~a:\n" (label-name label))
                        (print-x86-block block))))
      "\n"
      (format "\t.globl ~a\n" (label-name "main"))
      (format "~a:\n" (label-name "main"))
      (format "\tpushq\t%rbp\n")
      (format "\tmovq\t%rsp, %rbp\n")
      (format "\tsubq\t$~a, %rsp\n" (align stack-space 16))
      (format "\tjmp ~a\n" (label-name 'start))
      (format "~a:\n" (label-name 'conclusion))
      (format "\taddq\t$~a, %rsp\n" (align stack-space 16))
      (format "\tpopq\t%rbp\n")
      (format "\tretq\n")
      )]
    [else (error "print-x86, unmatched" e)]
    ))