1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The University of Glasgow 2002-2004
4 *
5 * Helper bits for the generic apply code (AutoApply.hc)
6 *
7 * -------------------------------------------------------------------------- */
9 #ifndef AUTOAPPLY_H
10 #define AUTOAPPLY_H
12 // Build a new PAP: function is in R1
13 // ret addr and m arguments taking up n words are on the stack.
14 // NB. x is a dummy argument attached to the 'for' label so that
15 // BUILD_PAP can be used multiple times in the same function.
16 #define BUILD_PAP(m,n,f,x) \
17 W_ pap; \
18 W_ size; \
19 W_ i; \
20 size = SIZEOF_StgPAP + WDS(n); \
21 HP_CHK_NP_ASSIGN_SP0(size,f); \
22 TICK_ALLOC_PAP(size, 0); \
23 CCCS_ALLOC(size); \
24 pap = Hp + WDS(1) - size; \
25 SET_HDR(pap, stg_PAP_info, CCCS); \
26 StgPAP_arity(pap) = HALF_W_(arity - m); \
27 StgPAP_fun(pap) = R1; \
28 StgPAP_n_args(pap) = HALF_W_(n); \
29 i = 0; \
30 for##x: \
31 if (i < n) { \
33 i = i + 1; \
34 goto for##x; \
35 } \
36 R1 = pap; \
38 jump %ENTRY_CODE(Sp(0)) [R1];
40 // Just like when we enter a PAP, if we're building a new PAP by applying more
41 // arguments to an existing PAP, we must construct the CCS for the new PAP as if
42 // we had entered the existing PAP from the current CCS. Otherwise, we lose any
43 // stack information in the existing PAP. See #5654, and the test T5654b-O0.
44 #ifdef PROFILING
45 #define ENTER_FUN_CCS_NEW_PAP(pap) \
46 ccall enterFunCCS(BaseReg "ptr", StgHeader_ccs(pap) "ptr");
47 #else
48 #define ENTER_FUN_CCS_NEW_PAP(pap) /* empty */
49 #endif
51 // Copy the old PAP, build a new one with the extra arg(s)
52 // ret addr and m arguments taking up n words are on the stack.
53 // NB. x is a dummy argument attached to the 'for' label so that
54 // BUILD_PAP can be used multiple times in the same function.
55 #define NEW_PAP(m,n,f,x) \
56 W_ pap; \
57 W_ new_pap; \
58 W_ size; \
59 W_ i; \
60 pap = R1; \
61 size = SIZEOF_StgPAP + WDS(TO_W_(StgPAP_n_args(pap))) + WDS(n); \
62 HP_CHK_NP_ASSIGN_SP0(size,f); \
63 TICK_ALLOC_PAP(size, 0); \
64 CCCS_ALLOC(size); \
65 ENTER_FUN_CCS_NEW_PAP(pap); \
66 new_pap = Hp + WDS(1) - size; \
67 SET_HDR(new_pap, stg_PAP_info, CCCS); \
68 StgPAP_arity(new_pap) = HALF_W_(arity - m); \
69 W_ n_args; \
70 n_args = TO_W_(StgPAP_n_args(pap)); \
71 StgPAP_n_args(new_pap) = HALF_W_(n_args + n); \
72 StgPAP_fun(new_pap) = StgPAP_fun(pap); \
73 i = 0; \
74 for1##x: \
75 if (i < n_args) { \
77 i = i + 1; \
78 goto for1##x; \
79 } \
80 i = 0; \
81 for2##x: \
82 if (i < n) { \
84 i = i + 1; \
85 goto for2##x; \
86 } \
87 R1 = new_pap; \