1 %************************************************************************
3 \section[CallWrap_C.lc]{``callWrapper'' stuff that can be written in C}
5 %************************************************************************
8 #define MAIN_REG_MAP /* These routines are all a bit special */
9 #define CALLWRAPPER_C /* Don't give standard declarations for wrappers */
13 %************************************************************************
15 \subsection[call-wrapping]{Routines to ``wrap'' special calls to C}
17 %************************************************************************
19 In most cases, this requires some assembly-language hacking (see the
20 discussion in @COptWraps.lh@.)
23 #if defined(__STG_GCC_REGS__)
25 # if defined(CALLER_SAVES_SYSTEM) || defined(CALLER_SAVES_USER)
27 callWrapper(STG_NO_ARGS)
61 CALLER_RESTORE_Base /* has to be first! */
72 CALLER_RESTORE_FltReg1
73 CALLER_RESTORE_FltReg2
74 CALLER_RESTORE_FltReg3
75 CALLER_RESTORE_FltReg4
76 CALLER_RESTORE_DblReg1
77 CALLER_RESTORE_DblReg2
78 CALLER_RESTORE_LngReg1
79 CALLER_RESTORE_LngReg2
87 CALLER_RESTORE_Liveness
90 /* These next two are restore-only */
91 CALLER_RESTORE_StdUpdRetVec
92 CALLER_RESTORE_StkStub
96 # endif /* defined(CALLER_SAVES_SYSTEM) || defined(CALLER_SAVES_USER) */
98 # if defined(CALLER_SAVES_SYSTEM)
100 callWrapper_safe(STG_NO_ARGS)
117 CALLER_RESTORE_Base /* has to be first! */
126 CALLER_RESTORE_Liveness
129 /* These next two are restore-only */
130 CALLER_RESTORE_StdUpdRetVec
131 CALLER_RESTORE_StkStub
135 # endif /* defined(CALLER_SAVES_SYSTEM) */
140 Anyone changing the definition of @callWrapper_GC@ should make
141 appropriate changes in the compiler (absCSyn/PprAbsC.lhs :: pprCCall).
143 The reason is that \tr{_ccall_GC_} and \tr{_casm_GC_} generate code like this:
148 _ccall_result = << do the call/asm>>;
154 This avoids limiting _ccall_GC_ to 6 arguments and makes it possible
155 to implement _ccall_GC_. (The local variable avoids the need for some
156 of the deeper magic hidden inside @GC_SETUP@, @GC_CCALL@ and
161 EXTFUN(EnterNodeCode);
163 void *__temp_esp, *__temp_eax;
165 void PerformGC_wrapper PROTO((W_)) WRAPPER_NAME(PerformGC);
166 void PerformGC_wrapper(args)
172 WRAPPER_SETUP(PerformGC,ret_addr,args)
174 WRAPPER_SETUP(PerformGC, ignore_me, ignore_me)
182 void __DISCARD__ (STG_NO_ARGS) { /*nothing*/ }
184 void StackOverflow_wrapper PROTO((W_,W_)) WRAPPER_NAME(StackOverflow);
185 void StackOverflow_wrapper(args1,args2)
189 void *ret_addr, *ignore_me;
190 WRAPPER_SETUP(StackOverflow,ret_addr,ignore_me)
192 WRAPPER_SETUP(StackOverflow, ignore_me, ignore_me)
194 if(StackOverflow(args1,args2)) {
200 void Yield_wrapper PROTO((W_)) WRAPPER_NAME(Yield);
201 void Yield_wrapper(args)
205 void *ret_addr, *ignore_me;
206 WRAPPER_SETUP(Yield, ret_addr, ignore_me)
208 WRAPPER_SETUP(Yield, ignore_me, ignore_me)
215 void PerformReschedule_wrapper PROTO((W_, W_)) WRAPPER_NAME(PerformReschedule);
216 void PerformReschedule_wrapper(liveness, always_reenter_node)
218 W_ always_reenter_node;
221 void *ret_addr, *ignore_me;
222 WRAPPER_SETUP(PerformReschedule, ret_addr, ignore_me)
224 WRAPPER_SETUP(PerformReschedule, ignore_me, ignore_me)
226 PerformReschedule(liveness, always_reenter_node);
230 /* Similar wrappers for all GrAnSim functions. */
231 /* NB: These are normal functions, which don't call ReSchedule. So we just */
232 /* have to safe/restore the registers. */
234 void GranSimAllocate_wrapper PROTO((I_, P_, W_)) WRAPPER_NAME(GranSimAllocate);
235 void GranSimAllocate_wrapper(n, node, liveness)
241 void *ret_addr, *ignore_me;
242 WRAPPER_SETUP(GranSimAllocate, ret_addr, ignore_me)
244 WRAPPER_SETUP(GranSimAllocate, ignore_me, ignore_me)
246 GranSimAllocate(n, node, liveness);
250 void GranSimUnallocate_wrapper PROTO((I_, P_, W_)) WRAPPER_NAME(GranSimUnallocate);
251 void GranSimUnallocate_wrapper(n, node, liveness)
257 void *ret_addr, *ignore_me;
258 WRAPPER_SETUP(GranSimUnallocate, ret_addr, ignore_me)
260 WRAPPER_SETUP(GranSimUnallocate, ignore_me, ignore_me)
262 GranSimUnallocate(n, node, liveness);
266 void GranSimFetch_wrapper PROTO((P_)) WRAPPER_NAME(GranSimFetch);
267 void GranSimFetch_wrapper(node)
271 void *ret_addr, *ignore_me;
272 WRAPPER_SETUP(GranSimFetch, ret_addr, ignore_me)
274 WRAPPER_SETUP(GranSimFetch, ignore_me, ignore_me)
280 void GranSimExec_wrapper PROTO((W_, W_, W_, W_, W_)) WRAPPER_NAME(GranSimExec);
281 void GranSimExec_wrapper(arith,branch,load,store,floats)
282 W_ arith,branch,load,store,floats;
285 void *ret_addr, *ignore_me;
286 WRAPPER_SETUP(GranSimExec, ret_addr, ignore_me)
288 WRAPPER_SETUP(GranSimExec, ignore_me, ignore_me)
290 GranSimExec(arith,branch,load,store,floats);
296 # endif /* CONCURRENT */
299 * In the threaded world, context switches may occur during one of these
300 * wrapped calls, and when we come back, our stack will have been trashed.
301 * If gcc, in all of its cleverness, tries to store any temporary values on
302 * the stack, we need to separate the restoration function. See the sparc
303 * code for an example.
306 SEPARATE_WRAPPER_RESTORE
308 #endif /* defined(__STG_GCC_REGS__) */
310 /* We can perform a runtime check that we have used @_ccall_GC_@ when
311 appropriate using this flag. */
312 StgInt inCCallGC = 0;
317 if (inCCallGC == 0) {
318 fprintf(stderr, "Error: entering a closure from C without using _ccall_GC_\n");