diff --git a/apply.s b/apply.s index 2d7109d..36d268c 100644 --- a/apply.s +++ b/apply.s @@ -14,10 +14,10 @@ main: thunkto %r12, $FUN2_code, $plus, $0 # apply first argument - thunkto %r12, $apply1, $2, %r12, %r11 + thunkto %r12, $apply, $2, %r12, %r11 # apply second argument (the p.a. function part is still in r12) - thunkto %r12, $apply1, $2, %r12, %r11 + thunkto %r12, $apply, $2, %r12, %r11 # print the result thunkto %r12, $print, $1, %r12 diff --git a/include/apply.s b/include/apply.s index 2b88dd0..0a0457d 100644 --- a/include/apply.s +++ b/include/apply.s @@ -1,6 +1,8 @@ .include "include/data.s" +#TODO apply1 seems obsolete by generic apply + # | fun | arg | -> cont .thunkcode apply1 thunkto %rsi, $apply1_fini, $3, 030(%rbp), %rbp, %rsi @@ -15,15 +17,15 @@ # the copying code is shared so let's do that first: pushq 020(%rbp) #push the new arg lea 030(%rsi), %rdx # the end (first arg) - lea (%rdx, %r11, 8), %rbx # address behind the last arg + lea (%rdx, %r11, 010), %rbx # address behind the last arg cmp %rdx, %rbx - jle apply1_fini_cont + jbe apply1_fini_cont apply1_fini_copy: sub $010, %rbx # iterate down pushq (%rbx) # push what we have cmp %rdx, %rbx # check if we are at the end - jg apply1_fini_copy # if not, continue + ja apply1_fini_copy # if not, continue apply1_fini_cont: add $1, %r11 pushq %r11 # new number of args of fun/thunk @@ -35,7 +37,7 @@ apply1_fini_cont: mov (%rsi), %rdi # infotable for the original fun mov -010(%rdi), %r12 # amount of args required to make the thunk cmp %r11, %r12 - jg apply1_fini_feed # not enough args, just make a bigger FUN + ja apply1_fini_feed # not enough args, just make a bigger FUN # if there was enough args, we simply have a thunk that we want to # continue evaluating, so let's jump to it. @@ -55,4 +57,111 @@ apply1_fini_feed: mov %rsp, %rsi # return the new FUN enter 040(%rbp) # jump to the continuation -# TODO generalize to N args +# | fun | arg[1] | arg[2] | ... | arg[args-1] | -> cont +.thunkcode apply + thunkto %rsi, $apply_fini, $2, %rbp, %rsi + 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) + + mov %r11, %r14 + add %r13, %r14 + cmp %r12, %r14 # do we have enough arguments? + 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 + lea 030(%r10, %rcx, 010), %rdx + apply_fini_o_tc_copy: + sub $010, %rdx + pushq (%rdx) + loop apply_fini_o_tc_copy + + # move all args from the closure + mov %r11, %rcx + lea 030(%rsi, %r11, 010), %rdx + apply_fini_o_fun_copy: + sub $010, %rdx + pushq (%rdx) + loop apply_fini_o_fun_copy + + # 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 + lea 030(%r10, %r13, 010), %rdx + apply_fini_o_tt_copy: + sub $010, %rdx + pushq (%rdx) + loop apply_fini_o_tt_copy + + # 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 diff --git a/include/macros.s b/include/macros.s index c52f6b0..051f147 100644 --- a/include/macros.s +++ b/include/macros.s @@ -39,21 +39,15 @@ _macros_s_file: \name: .endm -.macro thunkargs arg,args:vararg +.macro thunk arg,args:vararg .ifnb \arg - thunkargs \args + thunk \args pushq \arg .endif .endm -.macro thunk code:req,n:req,args:vararg - thunkargs \args - pushq \n - pushq \code -.endm - -.macro thunkto reg:req,code:req,n:req,args:vararg - thunk \code,\n,\args +.macro thunkto reg:req,args:vararg + thunk \args mov %rsp, \reg .endm