|
122 | 122 |
|
123 | 123 | ;; Label (listof Expr) -> Asm |
124 | 124 | (define (compile-ccall f es c) |
125 | | - (let ((stack-size (* 8 (length c)))) |
126 | | - (match es |
127 | | - [`() |
128 | | - `( |
129 | | - |
130 | | - (mov r15 rsp) |
131 | | - |
132 | | - ; change rsp to reflect the top of the stack |
133 | | - (sub rsp ,stack-size) |
| 125 | + (let* ((c0 (store-caller-save caller-saves c)) |
| 126 | + (c* (car c0)) |
| 127 | + (c1 (compile-es-ffi es c* 0)) |
| 128 | + (c2 (cdr (load-caller-save caller-saves c))) |
| 129 | + (stack-size (* 8 (length c*)))) |
| 130 | + |
| 131 | + ; We don't actually have to do all caller-save (that's a lot!) |
| 132 | + ; Just the ones that our compiler emits |
| 133 | + `(,@(cdr c0) |
| 134 | + |
| 135 | + ,@c1 |
| 136 | + (mov r15 rsp) ; Using the fact that r15 is callee save |
| 137 | + |
| 138 | + ; change rsp to reflect the top of the stack |
| 139 | + (sub rsp ,stack-size) |
| 140 | + |
| 141 | + ; align rsp to safest 16-byte aligned spot |
| 142 | + (and rsp -16) |
| 143 | + |
| 144 | + ; Actually call the function |
| 145 | + (call ,f) |
| 146 | + |
| 147 | + ; Restore our stack |
| 148 | + (mov rsp r15) |
| 149 | + |
| 150 | + ; Put the caller-saved values back |
| 151 | + ,@c2))) |
| 152 | + |
| 153 | +;; The registers that we can use to pass arguments to C functions |
| 154 | +;; (in the right order) |
| 155 | +;; |
| 156 | +(define arg-regs '(rdi rsi rdx rcx r8 r9)) |
| 157 | +(define callee-saves '(rbp rbx r12 r13 r14 r15)) |
| 158 | +(define caller-saves '(rcx rdx rdi rsi r8 r9 r10 r11)) |
| 159 | + |
| 160 | +; Make sure we store every caller-save register that we care about on the stack. |
| 161 | +; This is basiclaly a foldMR, but I need to learn more Racket |
| 162 | +(define (store-caller-save rs c) |
| 163 | + (match rs |
| 164 | + ['() (cons c '())] |
| 165 | + [(cons r rs) |
| 166 | + (match (store-caller-save rs c) |
| 167 | + [(cons d asm) |
| 168 | + (cons (cons #f d) |
| 169 | + (append asm `((mov (offset rsp ,(- (add1 (length d)))) ,r))))])])) |
| 170 | + |
| 171 | +; Same as above but inverse |
| 172 | +(define (load-caller-save rs c) |
| 173 | + (match rs |
| 174 | + ['() (cons c '())] |
| 175 | + [(cons r rs) |
| 176 | + (match (load-caller-save rs c) |
| 177 | + [(cons d asm) |
| 178 | + (cons (cons #f d) |
| 179 | + (append asm `((mov ,r (offset rsp ,(- (add1 (length d))))))))])])) |
| 180 | + |
| 181 | + |
| 182 | +;; JMCT: I keep 'programming in Haskell in Racket' and I need to stop that... |
| 183 | +;; the above is my monadic habits biting me |
134 | 184 |
|
135 | | - ; align rsp to safest 16-byte aligned spot |
136 | | - (and rsp -16) |
137 | | - |
138 | | - (call ,f) |
139 | | - |
140 | | - (mov rsp r15) |
| 185 | +;; (Listof LExpr) CEnv -> Asm |
| 186 | +(define (compile-es-ffi es c i) |
| 187 | + (match es |
| 188 | + ['() '()] |
| 189 | + [(cons e es) |
| 190 | + (let ((c0 (compile-e e c)) |
| 191 | + (cs (compile-es-ffi es c (add1 i)))) |
| 192 | + `(,@c0 |
| 193 | + (sar rax ,imm-shift) |
| 194 | + (mov ,(list-ref arg-regs i) rax) ; Put the result in the appropriate register |
| 195 | + ,@cs))])) |
141 | 196 |
|
142 | | - )] |
143 | | - [_ `()]))) |
144 | 197 |
|
145 | 198 | ;; (Listof Variable) Label (Listof Variable) CEnv -> Asm |
146 | 199 | (define (compile-λ xs f ys c) |
|
0 commit comments