|
47 | 47 | (match l |
48 | 48 | [(Lam '() xs e) (error "Lambdas must be labelled before code gen (contact your compiler writer)")] |
49 | 49 | [(Lam f xs e) |
50 | | - (let* ((free (fvs e)) |
| 50 | + (let* ((free (remq* xs (fvs e))) |
51 | 51 | ; leave space for RIP |
52 | 52 | (env (parity (cons #f (cons #f (reverse (append xs free))))))) |
53 | 53 | (seq (Label (symbol->label f)) |
| 54 | + (%% "Compiling the body of the function") |
| 55 | + (%% (~a "free vars: " free)) |
| 56 | + (%% (~a "args: " xs)) |
| 57 | + (%% (~a "env: " env)) |
54 | 58 | ; we need the #args on the frame, not the length of the entire |
55 | 59 | ; env (which may have padding) |
56 | | - (compile-tail-e e env (length (append xs free))) |
| 60 | + ; Ignore tail calls for now |
| 61 | + (compile-e e env) |
57 | 62 | (Ret)))])) |
58 | 63 |
|
59 | 64 | (define (parity c) |
|
108 | 113 |
|
109 | 114 | ; Save the environment |
110 | 115 | (%% "Begin saving the env") |
| 116 | + (%% (~a "free vars: " ys)) |
111 | 117 | (Mov r8 (length ys)) |
| 118 | + |
112 | 119 | (Mov (Offset rbx 8) r8) |
113 | 120 | (Mov r9 rbx) |
114 | 121 | (Add r9 16) |
|
137 | 144 | ; far away from r9 the next item should be |
138 | 145 | (copy-env-to-heap fvs c (+ 8 i)))])) |
139 | 146 |
|
140 | | -;; Id CEnv -> Asm |
141 | | -(define (compile-fun f) |
142 | | - ; Load the address of the label into rax |
143 | | - (seq (Lea rax (symbol->label f)) |
144 | | - ; Copy the value onto the heap |
145 | | - (Mov (Offset rbx 0) rax) |
146 | | - ; Copy the heap address into rax |
147 | | - (Mov rax rbx) |
148 | | - ; Tag the value as a proc |
149 | | - (Or rax type-proc) |
150 | | - ; Bump the heap pointer |
151 | | - (Add rbx 8))) |
152 | | - |
153 | 147 | ;; Op0 CEnv -> Asm |
154 | 148 | (define (compile-prim0 p c) |
155 | 149 | (match p |
|
257 | 251 | (Or rax type-cons) |
258 | 252 | (Add rbx 16))]))) |
259 | 253 |
|
260 | | - |
261 | | - |
262 | 254 | ;; Id [Listof Expr] CEnv -> Asm |
263 | | -;; Here's why this code is so gross: you have to align the stack for the call |
264 | | -;; but you have to do it *before* evaluating the arguments es, because you need |
265 | | -;; es's values to be just above 'rsp when the call is made. But if you push |
266 | | -;; a frame in order to align the call, you've got to compile es in a static |
267 | | -;; environment that accounts for that frame, hence: |
| 255 | +;; Here's (part of) why this code is so gross: you have to align the stack for |
| 256 | +;; the call but you have to do it *before* evaluating the arguments es, |
| 257 | +;; because you need es's values to be just above 'rsp when the call is made. |
| 258 | +;; But if you push a frame in order to align the call, you've got to compile es |
| 259 | +;; in a static environment that accounts for that frame, hence: |
268 | 260 | (define (compile-call f es c) |
269 | 261 | (let* ((cnt (length es)) |
270 | 262 | (aligned (even? (+ cnt (length c)))) |
|
275 | 267 | (c++ (cons #f c+))) |
276 | 268 | (seq |
277 | 269 |
|
278 | | - (%% (~a "Begin compile-call: aligned = " aligned " function: " f)) |
| 270 | + (%% "Begin compile-call") |
279 | 271 | ; Adjust the stack for alignment, if necessary |
280 | 272 | (if aligned |
281 | 273 | (seq) |
|
286 | 278 | (compile-e f c+) |
287 | 279 | (%% "Push function on stack") |
288 | 280 | (Push rax) |
289 | | - |
290 | | - (%% (~a "Begin compile-es: es = " es)) |
| 281 | + |
291 | 282 | ; Generate the code for the arguments |
292 | 283 | ; all results will be put on the stack (compile-es does this) |
293 | 284 | (compile-es es c++) |
|
299 | 290 | (Mov rax (Offset rsp (* 8 cnt))) |
300 | 291 | (assert-proc rax) |
301 | 292 | (Xor rax type-proc) |
302 | | - |
| 293 | + |
303 | 294 | (%% "Get closure env") |
304 | 295 | (copy-closure-env-to-stack) |
305 | 296 | (%% "finish closure env") |
|
326 | 317 | (define (compile-tail-call e0 es c) |
327 | 318 | (let ((cnt (length es))) |
328 | 319 | (seq |
| 320 | + (%% (~a "Begin compile-tail-call: function = " e0)) |
329 | 321 | ; Generate the code for the thing being called |
330 | 322 | ; and push the result on the stack |
331 | 323 | (compile-e e0 c) |
| 324 | + (%% "Push function on stack") |
332 | 325 | (Push rax) |
333 | 326 |
|
334 | 327 | ; Generate the code for the arguments |
335 | 328 | ; all results will be put on the stack (compile-es does this) |
336 | 329 | (compile-es es (cons #f c)) |
337 | 330 |
|
338 | 331 | ; Reuse the stack frame (as it's a tail call) |
339 | | - (move-args cnt (+ cnt (add1 (in-frame c)))) |
| 332 | + (move-args cnt (+ cnt (+ 2 (in-frame c)))) |
340 | 333 |
|
341 | 334 | ; Get the function being called off the stack |
342 | 335 | ; Ensure it's a proc and remove the tag |
|
347 | 340 |
|
348 | 341 | ; Bump stack pointer (this is where the tail-call |
349 | 342 | ; savings kick in) |
350 | | - (Add rsp (* 8 (+ cnt (add1 (in-frame c))))) |
| 343 | + (Add rsp (* 8 (+ cnt (+ 2 (in-frame c))))) |
351 | 344 |
|
352 | 345 | (copy-closure-env-to-stack) |
353 | 346 |
|
|
359 | 352 | (let ((copy-loop (symbol->label (gensym 'copy_closure))) |
360 | 353 | (copy-done (symbol->label (gensym 'copy_done)))) |
361 | 354 | (seq |
| 355 | + |
362 | 356 | (Mov r8 (Offset rax 8)) ; length |
363 | 357 | (Mov r9 rax) |
364 | 358 | (Add r9 16) ; start of env |
|
0 commit comments