.include "include/data.s" # | fun | arg[1] | arg[2] | ... | arg[args-1] | -> cont .thunkcode apply needs_alloc $040 thunkto %rsi, $apply_fini, $2, %rbp, %rsi # TODO: this needs to be blackholed here, but we need to copy out all # the args because the blackhole can't hold them enter 020(%rbp) # fun -> | ret (with args) | cont | .thunkcode apply_fini mov (%rsi), %r9 # infotable for the original function mov 020(%rbp), %r10 # the original thunk mov 020(%rsi), %r11 # amount of args applied in the closure mov -010(%r9), %r12 # amount of args required to make a thunk mov 010(%r10), %r13 # amount of args in the original thunk sub $1, %r13 # amount of args we want to apply (the 1st one is the FUN) lea (%r11, %r13), %r14 # total amount arguments we have lea 050(%r14), %r15 # how much memory this needs in extreme needs_alloc %r15 # worst-case memory is: we make a thunk (2 headers + some args) and a # leftover closure (3 headers + rest of args) # Now that we have enough memory, do we have enough arguments to do anything? cmp %r12, %r14 ja apply_fini_o apply_fini_pt: # Not enough args or exactly enough args. # Basically make a function or a thunk that is almost the same. # first move thunk params mov %r13, %rcx cmp $0, %rcx jz apply_fini_pt_thunk_skip lea 030(%r10, %r13, 010), %rdx apply_fini_pt_thunk_copy: sub $010, %rdx pushq (%rdx) loop apply_fini_pt_thunk_copy apply_fini_pt_thunk_skip: # now move the fun params mov %r11, %rcx cmp $0, %rcx jz apply_fini_pt_fun_skip lea 030(%rsi, %r11, 010), %rdx apply_fini_pt_fun_copy: sub $010, %rdx pushq (%rdx) loop apply_fini_pt_fun_copy apply_fini_pt_fun_skip: # make a thunk thunk 010(%rsi), %r14 cmp %r12, %r14 # are we precisely at the right amount of arguments for a thunk? je apply_fini_pt_thunk # if not, wrap a closure apply_fini_pt_closure: thunkto %rsi, %r9 # replace the original thunk with an indirect mov %rsi, 010(%r10) movq $IND_code, (%r10) # return the closure (%rsi) to the original continuation enter 030(%rbp) apply_fini_pt_thunk: # it is a thunk, point to it and start evaluating it mov %rsp, 010(%r10) movq $IND_code, (%r10) # tell the thunk to evaluate into the original continuation mov 030(%rbp), %rsi enter %rsp apply_fini_o: #TODO needs to be tested # too many args, we need to split off a bit # first move just the right amount of args off the thunk mov %r12, %rcx sub %r11, %rcx cmp $0, %rcx jz apply_fini_o_tc_skip lea 030(%r10, %rcx, 010), %rdx apply_fini_o_tc_copy: sub $010, %rdx pushq (%rdx) loop apply_fini_o_tc_copy apply_fini_o_tc_skip: # move all args from the closure mov %r11, %rcx cmp $0, %rcx jz apply_fini_o_fun_skip lea 030(%rsi, %r11, 010), %rdx apply_fini_o_fun_copy: sub $010, %rdx pushq (%rdx) loop apply_fini_o_fun_copy apply_fini_o_fun_skip: # make the thunk for the application that can be evaluated later thunkto %r15, 010(%rsi), %r14 # now make a thunk with the rest of the stuff mov %r14, %rcx sub %r12, %rcx mov %rcx, %r14 # backup leftover count for later cmp $0, %rcx jz apply_fini_o_tt_skip lea 030(%r10, %r13, 010), %rdx apply_fini_o_tt_copy: sub $010, %rdx pushq (%rdx) loop apply_fini_o_tt_copy apply_fini_o_tt_skip: # finish the leftovers thunk add $1, %r14 # (1 fun to apply to + args) thunk $apply,%r14,%r15 # replace the original thunk with an indirect mov %rsp, 010(%r10) movq $IND_code, (%r10) # evaluate to the original continuation mov 030(%rbp), %rsi enter %rsp