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