#lang racket (require racket/list) (provide select-instructions) (define (select-instructions p) (match p [`(program ,data ,body) `(AArch64VProgram ,data ,(select-instructions-section (car body)))])) (define (select-instructions-section sec) (match sec [`(,label . ,statement) `(,label . (Block `() ,(select-instructions-stmt statement)))])) (define (select-instructions-stmt stmt) (match stmt [`(return ,exp) (select-instructions-return exp)] [`(seq (assign ,var ,exp) ,next-stmt) (append (select-instructions-assign var exp) (select-instructions-stmt next-stmt))])) (define (select-instructions-assign var exp) (match exp [(? symbol?) (list `(Instr mov ((Var ,var) (Var ,exp))))] [(? fixnum?) (list `(Instr mov ((Var ,var) (Imm ,exp))))] [`(read) (select-instructions-read `(Var ,var))] [`(- ,e) (select-instructions-neg e `(Var ,var))] [`(+ ,a ,b) (select-instructions-add a b `(Var ,var))])) (define (select-instructions-return exp) (append (match exp [(? symbol?) (list `(Instr mov (x0 (Var ,exp))))] [(? fixnum?) (list `(Instr mov (x0 (Imm ,exp))))] [`(read) (select-instructions-read 'x0)] [`(- ,e) (select-instructions-neg e 'x0)] [`(+ ,a ,b) (select-instructions-add a b 'x0)]) `[(Instr b (conclusion))])) (define (select-instructions-read dest) (if (eq? dest 'x0) (list `(Instr bl _builtin_read)) (list `(Instr bl _builtin_read) `(Instr mov (,dest x0))))) (define (select-instructions-neg exp dest) (begin (define var-exp (if (fixnum? exp) `(Imm ,exp) `(Var ,exp))) (list `(Instr neg (,dest ,var-exp))))) (define (select-instructions-add a b dest) (begin ; if e1 is an imm, swap (define-values (e1 e2) (imm-to-right a b)) (define num-imm (count fixnum? (list e1 e2))) (match num-imm [0 (list `(Instr add (,dest (Var ,e1) (Var ,e2))))] [1 (list `(Instr add (,dest (Var ,e1) (Imm ,e2))))] [2 (list `(Instr mov (,dest (Imm ,e1))) `(Instr add (,dest ,dest (Imm ,e2))))]))) (define (imm-to-right e1 e2) (if (and (fixnum? e1) (not (fixnum? e2))) (values e2 e1) (values e1 e2)))