Deduplicate `HaskellMachRegs.h` and `RtsMachRegs.h` headers
[ghc.git] / rts / StgStartup.cmm
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2012
4  *
5  * Code for starting, stopping and restarting threads.
6  *
7  * This file is written in a subset of C--, extended with various
8  * features specific to GHC.  It is compiled by GHC directly.  For the
9  * syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
10  *
11  * ---------------------------------------------------------------------------*/
12
13 #include "Cmm.h"
14
15 /*
16  * This module contains the two entry points and the final exit point
17  * to/from the Haskell world.  We can enter either by:
18  *
19  *   a) returning to the address on the top of the stack, or
20  *   b) entering the closure on the top of the stack
21  *
22  * the function stg_stop_thread_entry is the final exit for a
23  * thread: it is the last return address on the stack.  It returns
24  * to the scheduler marking the thread as finished.
25  */
26
27 #define CHECK_SENSIBLE_REGS()                           \
28     ASSERT(Hp != 0);                                    \
29     ASSERT(HpAlloc == 0);                               \
30     ASSERT(Sp != 0);                                    \
31     ASSERT(SpLim != 0);                                 \
32     ASSERT(SpLim - WDS(RESERVED_STACK_WORDS) <= Sp);
33
34 /* -----------------------------------------------------------------------------
35    Returning from the STG world.
36    -------------------------------------------------------------------------- */
37
38 INFO_TABLE_RET(stg_stop_thread, STOP_FRAME,
39                W_ info_ptr,
40                PROF_HDR_FIELDS(W_,p1,p2))
41 /* no return list: explicit stack layout */
42 {
43     /*
44        The final exit.
45
46        The top-top-level closures (e.g., "main") are of type "IO a".
47        When entered, they perform an IO action and return an 'a' in R1.
48
49        We save R1 on top of the stack where the scheduler can find it,
50        tidy up the registers and return to the scheduler.
51
52        We Leave the stack looking like this:
53
54                 +----------------+
55                 |      -------------------> return value
56                 +----------------+
57                 | stg_enter_info |
58                 +----------------+
59
60        The stg_enter_info is just a dummy info table so that the
61        garbage collector can understand the stack (there must always
62        be an info table on top of the stack).
63     */
64
65     // See Note [Unwinding foreign exports on x86-64].
66 #if defined(x86_64_HOST_ARCH)
67     unwind UnwindReturnReg = STG_RUN_JMP;
68 #else
69     // FIXME: Fill in for other platforms
70     unwind UnwindReturnReg = return;
71 #endif
72
73     Sp = Sp + SIZEOF_StgStopFrame - WDS(2);
74     Sp(1) = R1;
75     Sp(0) = stg_enter_info;
76
77     StgTSO_what_next(CurrentTSO) = ThreadComplete::I16;
78
79     SAVE_THREAD_STATE();
80
81     /* The return code goes in BaseReg->rRet, and BaseReg is returned in R1 */
82     StgRegTable_rRet(BaseReg) = ThreadFinished;
83     R1 = BaseReg;
84
85     jump StgReturn [R1];
86 }
87
88 /* -----------------------------------------------------------------------------
89    Start a thread from the scheduler by returning to the address on
90    the top of the stack.  This is used for all entries to STG code
91    from C land.
92
93    On the way back, we (usually) pass through stg_returnToSched which saves
94    the thread's state away nicely.
95    -------------------------------------------------------------------------- */
96
97 stg_returnToStackTop /* no args: explicit stack layout */
98 {
99   LOAD_THREAD_STATE();
100   CHECK_SENSIBLE_REGS();
101   jump %ENTRY_CODE(Sp(0)) [];
102 }
103
104 stg_returnToSched /* no args: explicit stack layout */
105 {
106   W_ r1;
107   r1 = R1; // foreign calls may clobber R1
108   SAVE_THREAD_STATE();
109   foreign "C" threadPaused(MyCapability() "ptr", CurrentTSO);
110   R1 = r1;
111   jump StgReturn [R1];
112 }
113
114 // A variant of stg_returnToSched that doesn't call threadPaused() on the
115 // current thread.  This is used for switching from compiled execution to the
116 // interpreter, where calling threadPaused() on every switch would be too
117 // expensive.
118 //
119 // See Note [avoiding threadPaused] in Interpreter.c
120 //
121 stg_returnToSchedNotPaused /* no args: explicit stack layout */
122 {
123   SAVE_THREAD_STATE();
124   jump StgReturn [R1];
125 }
126
127 // A variant of stg_returnToSched, but instead of returning directly to the
128 // scheduler, we jump to the code fragment pointed to by R2.  This lets us
129 // perform some final actions after making the thread safe, such as unlocking
130 // the MVar on which we are about to block in SMP mode.
131 stg_returnToSchedButFirst /* no args: explicit stack layout */
132 {
133   W_ r1, r2, r3;
134   r1 = R1;
135   r2 = R2;
136   r3 = R3;
137   SAVE_THREAD_STATE();
138   // foreign calls may clobber R1/R2/.., so we save them above
139   foreign "C" threadPaused(MyCapability() "ptr", CurrentTSO);
140   R1 = r1;
141   R2 = r2;
142   R3 = r3;
143   jump R2 [R1,R3];
144 }
145
146 stg_threadFinished /* no args: explicit stack layout */
147 {
148   StgRegTable_rRet(BaseReg) = ThreadFinished;
149   R1 = BaseReg;
150   jump StgReturn [R1];
151 }
152
153 /* -----------------------------------------------------------------------------
154     Strict IO application - performing an IO action and entering its result.
155
156     rts_evalIO() lets you perform Haskell IO actions from outside of
157     Haskell-land, returning back to you their result. Want this result
158     to be evaluated to WHNF by that time, so that we can easily get at
159     the int/char/whatever using the various get{Ty} functions provided
160     by the RTS API.
161
162     stg_forceIO takes care of this, performing the IO action and entering
163     the results that comes back.
164
165     ------------------------------------------------------------------------- */
166
167 INFO_TABLE_RET(stg_forceIO, RET_SMALL, P_ info_ptr)
168     return (P_ ret)
169 {
170     ENTER(ret);
171 }
172
173 /* Called when compiled with -falignment-sanitisation on alignment failure */
174 stg_badAlignment_entry
175 {
176   foreign "C" barf();
177 }