1 \section[StgMiniInt]{The ``mini-interpreter'' that drives the STG machine}
3 % this file is part of the C-as-assembler document
9 For portable~C, there really is a mini-interpreter that repeatedly
10 grabs the continuation from each code fragment and jumps to it.
12 In portable~C, we also have a ``debugging'' version of the
13 mini-interpreter which does ``hygiene-checking'' of the stacks/heap(?)
14 each time it regains control. This is deeply wonderful when the
15 compiler's generating duff code and things are badly broken!
17 For optimised~C, the mini-interpreter really {\em doesn't} do anything
18 remotely interpretive. It just jumps off into a Haskell Threaded
19 World, dropping a label for \tr{_miniInterpretEnd} so we'll have a
20 place to eventually come back to.
22 A complication in optimised~C: Because we completely nuke C-stack
23 activity (pushing/popping frames, moving register-windows) within the
24 Haskell-threaded world, we need to ensure there is enough C-stack
25 space actually present to satisfy the code that GCC generated.
27 IMPORTANT POINT: the mini-interpreter is supposed to be {\em generic}.
28 It is not only for the Haskell Threaded World---the storage manager
29 may use it as well. So: whatever threaded world is in operation has
30 to handle its own register saving/restoring, and such grimy details.
31 For an example, see the @startStgWorld@, @stopStgWorld@ pair of
34 %************************************************************************
36 \subsection[StgMiniInt-optimised]{Mini-interpreter for ``optimised~C''}
38 %************************************************************************
40 Unusually, for mini-interpreters, the ``optimised~C'' case involves
44 #if defined(__STG_TAILJUMPS__) && defined(__GNUC__)
47 miniInterpret(start_cont)
51 * MINI_INTERPRETER_SETUP _must_ save _all_ callee-saves registers, because
52 * the caller expects them to be saved if they are used, but the threaded
53 * code never saaves anything (all function prologues have been removed).
56 MINI_INTERPRETER_SETUP
59 * starts Haskell world by _calling_ "start_cont"
61 * Make this a JMP_ and dead code elimination will make you unhappy.
63 * You will be even more unhappy with a registerized HP build, because
64 * the continuation passed in here is actually the address of a function
65 * ADT, and not the address where the function really begins.
70 * and drops a label for "miniInterpretEnd" right here, along
71 * with any cleanup that has to be done before we return.
73 * _Always_ RESUME_(miniInterpretEnd). Never JMP_(miniInterpretEnd).
82 %************************************************************************
84 \subsection[StgMiniInt-portable]{Mini-interpreter for ``portable~C''}
86 %************************************************************************
89 #else /* ! (__STG_TAILJUMPS__ && __GNUC__) */
92 /* by which we mean the Standard C Library stuff */
95 %************************************************************************
97 \subsubsection[StgMiniInt-portable-normal]{Normal mini-interpreter for ``portable~C''}
99 %************************************************************************
101 The static @jmp_environment@ variable allows @miniInterpret@ to
102 communicate with @miniInterpretEnd@.
104 Because @miniInterpret@ may be used recursively, we carefully
105 save and restore the whole of @jmp_environment@.
108 static jmp_buf jmp_environment;
110 void bcopy PROTO((char *, char *, int)); /*ToDo: properly?*/
113 miniInterpret(start_cont)
114 StgFunPtr start_cont;
116 StgFunPtr continuation = (StgFunPtr) start_cont;
118 bcopy((char *) jmp_environment, (char *) save_buf, sizeof(jmp_buf));
119 /* Save jmp_environment for previous call to miniInterpret */
121 if (setjmp(jmp_environment) == 0) {
124 /* unrolled for a little speed */
125 continuation = (StgFunPtr) (continuation)();
126 continuation = (StgFunPtr) (continuation)();
127 continuation = (StgFunPtr) (continuation)();
128 continuation = (StgFunPtr) (continuation)();
129 continuation = (StgFunPtr) (continuation)();
134 /* Restore jmp_environment for previous call */
135 bcopy((char *) save_buf, (char *) jmp_environment, sizeof(jmp_buf));
137 /* ToDo: restore real registers ... (see longjmp) */
140 Note that on returning (after miniInterpretEnd is called)
141 the values variables declared as real machine registers
146 void miniInterpretEnd(STG_NO_ARGS)
148 /* ToDo: save real register in something somewhere */
149 longjmp(jmp_environment, 1);
152 #endif /* ! __STG_TAILJUMPS__ */