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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/* -----------------------------------------------------------------------------
*
* (c) The University of Glasgow 2002-2004
*
* Helper bits for the generic apply code (AutoApply.hc)
*
* -------------------------------------------------------------------------- */
#ifndef AUTOAPPLY_H
#define AUTOAPPLY_H
// Build a new PAP: function is in R1
// ret addr and m arguments taking up n words are on the stack.
// NB. x is a dummy argument attached to the 'for' label so that
// BUILD_PAP can be used multiple times in the same function.
#define BUILD_PAP(m,n,f,x) \
W_ pap; \
W_ size; \
W_ i; \
size = SIZEOF_StgPAP + WDS(n); \
HP_CHK_NP_ASSIGN_SP0(size,f); \
TICK_ALLOC_PAP(size, 0); \
CCCS_ALLOC(size); \
pap = Hp + WDS(1) - size; \
SET_HDR(pap, stg_PAP_info, CCCS); \
StgPAP_arity(pap) = HALF_W_(arity - m); \
StgPAP_fun(pap) = R1; \
StgPAP_n_args(pap) = HALF_W_(n); \
i = 0; \
for##x: \
if (i < n) { \
StgPAP_payload(pap,i) = Sp(1+i); \
i = i + 1; \
goto for##x; \
} \
R1 = pap; \
Sp_adj(1 + n); \
jump %ENTRY_CODE(Sp(0)) [R1];
// Just like when we enter a PAP, if we're building a new PAP by applying more
// arguments to an existing PAP, we must construct the CCS for the new PAP as if
// we had entered the existing PAP from the current CCS. Otherwise, we lose any
// stack information in the existing PAP. See #5654, and the test T5654b-O0.
#ifdef PROFILING
#define ENTER_FUN_CCS_NEW_PAP(pap) \
ccall enterFunCCS(BaseReg "ptr", StgHeader_ccs(pap) "ptr");
#else
#define ENTER_FUN_CCS_NEW_PAP(pap) /* empty */
#endif
// Copy the old PAP, build a new one with the extra arg(s)
// ret addr and m arguments taking up n words are on the stack.
// NB. x is a dummy argument attached to the 'for' label so that
// BUILD_PAP can be used multiple times in the same function.
#define NEW_PAP(m,n,f,x) \
W_ pap; \
W_ new_pap; \
W_ size; \
W_ i; \
pap = R1; \
size = SIZEOF_StgPAP + WDS(TO_W_(StgPAP_n_args(pap))) + WDS(n); \
HP_CHK_NP_ASSIGN_SP0(size,f); \
TICK_ALLOC_PAP(size, 0); \
CCCS_ALLOC(size); \
ENTER_FUN_CCS_NEW_PAP(pap); \
new_pap = Hp + WDS(1) - size; \
SET_HDR(new_pap, stg_PAP_info, CCCS); \
StgPAP_arity(new_pap) = HALF_W_(arity - m); \
W_ n_args; \
n_args = TO_W_(StgPAP_n_args(pap)); \
StgPAP_n_args(new_pap) = HALF_W_(n_args + n); \
StgPAP_fun(new_pap) = StgPAP_fun(pap); \
i = 0; \
for1##x: \
if (i < n_args) { \
StgPAP_payload(new_pap,i) = StgPAP_payload(pap,i); \
i = i + 1; \
goto for1##x; \
} \
i = 0; \
for2##x: \
if (i < n) { \
StgPAP_payload(new_pap,n_args+i) = Sp(1+i); \
i = i + 1; \
goto for2##x; \
} \
R1 = new_pap; \
Sp_adj(n+1); \
jump %ENTRY_CODE(Sp(0)) [R1];
// Jump to target, saving CCCS and restoring it on return
#if defined(PROFILING)
#define jump_SAVE_CCCS(target,...) \
Sp(-1) = CCCS; \
Sp(-2) = stg_restore_cccs_info; \
Sp_adj(-2); \
jump (target) [__VA_ARGS__]
#else
#define jump_SAVE_CCCS(target,...) jump (target) [__VA_ARGS__]
#endif
#endif /* APPLY_H */
|