aboutsummaryrefslogtreecommitdiff
path: root/include/apply.s
blob: 2b88dd0ca1e84f482fefab27dbe6b624b39867b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

.include "include/data.s"

# | fun | arg | -> cont
.thunkcode apply1
	thunkto %rsi, $apply1_fini, $3, 030(%rbp), %rbp, %rsi
	enter 020(%rbp) # evaluate fun

# fun -> | arg | ret | cont |
.thunkcode apply1_fini
	# we now know that fun points to a FUN with at least one arg missing.
	# we're certainly going to copy a lot of args.
	mov 020(%rsi), %r11 # amount of args applied now

	# 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

	cmp %rdx, %rbx
	jle 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
apply1_fini_cont:
	add $1, %r11
	pushq %r11 # new number of args of fun/thunk
	pushq 010(%rsi) # thunk code pointer

	# copying of all args and their thunky header is now done, let's find
	# out how we need to finish it.

	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

	# if there was enough args, we simply have a thunk that we want to
	# continue evaluating, so let's jump to it.
	mov 030(%rbp), %rdi # load the original thunk
	mov %rsp, 010(%rdi) # set indirect to the new thunk
	movq $IND_code, 0(%rdi)
	mov 040(%rbp), %rsi # set continuation to the original continuation
	enter %rsp # evaluate the new thunk

apply1_fini_feed:
	# if there were not enough args, we push the function info and return
	pushq (%rsi) # copy the function infoptr

	mov 030(%rbp), %rdi # load the original thunk
	mov %rsp, 010(%rdi) # set the indirect to the new FUN
	movq $IND_code, 0(%rdi)
	mov %rsp, %rsi # return the new FUN
	enter 040(%rbp) # jump to the continuation

# TODO generalize to N args