[project @ 2001-02-08 14:36:21 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsAPI.c
1 /* ----------------------------------------------------------------------------
2  * $Id: RtsAPI.c,v 1.25 2001/02/08 14:36:21 simonmar Exp $
3  *
4  * (c) The GHC Team, 1998-2001
5  *
6  * API for invoking Haskell functions via the RTS
7  *
8  * --------------------------------------------------------------------------*/
9
10 #include "Rts.h"
11 #include "Storage.h"
12 #include "RtsAPI.h"
13 #include "SchedAPI.h"
14 #include "RtsFlags.h"
15 #include "RtsUtils.h"
16 #include "Prelude.h"
17
18 /* ----------------------------------------------------------------------------
19    Building Haskell objects from C datatypes.
20    ------------------------------------------------------------------------- */
21 HaskellObj
22 rts_mkChar (HsChar c)
23 {
24   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
25   p->header.info = Czh_con_info;
26   p->payload[0]  = (StgClosure *)(StgChar)c;
27   return p;
28 }
29
30 HaskellObj
31 rts_mkInt (HsInt i)
32 {
33   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
34   p->header.info = Izh_con_info;
35   p->payload[0]  = (StgClosure *)(StgInt)i;
36   return p;
37 }
38
39 HaskellObj
40 rts_mkInt8 (HsInt8 i)
41 {
42   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
43   p->header.info = I8zh_con_info;
44   /* Make sure we mask out the bits above the lowest 8 */
45   p->payload[0]  = (StgClosure *)(StgInt)((unsigned)i & 0xff);
46   return p;
47 }
48
49 HaskellObj
50 rts_mkInt16 (HsInt16 i)
51 {
52   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
53   p->header.info = I16zh_con_info;
54   /* Make sure we mask out the relevant bits */
55   p->payload[0]  = (StgClosure *)(StgInt)((unsigned)i & 0xffff);
56   return p;
57 }
58
59 HaskellObj
60 rts_mkInt32 (HsInt32 i)
61 {
62   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
63   p->header.info = I32zh_con_info;
64   p->payload[0]  = (StgClosure *)(StgInt)i;
65   return p;
66 }
67
68 HaskellObj
69 rts_mkInt64 (HsInt64 i)
70 {
71   long long *tmp;
72   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,2));
73   p->header.info = I64zh_con_info;
74   tmp  = (long long*)&(p->payload[0]);
75   *tmp = (StgInt64)i;
76   return p;
77 }
78
79 HaskellObj
80 rts_mkWord (HsWord i)
81 {
82   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
83   p->header.info = Wzh_con_info;
84   p->payload[0]  = (StgClosure *)(StgWord)i;
85   return p;
86 }
87
88 HaskellObj
89 rts_mkWord8 (HsWord8 w)
90 {
91   /* see rts_mkInt* comments */
92   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
93   p->header.info = W8zh_con_info;
94   p->payload[0]  = (StgClosure *)(StgWord)(w & 0xff);
95   return p;
96 }
97
98 HaskellObj
99 rts_mkWord16 (HsWord16 w)
100 {
101   /* see rts_mkInt* comments */
102   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
103   p->header.info = W16zh_con_info;
104   p->payload[0]  = (StgClosure *)(StgWord)(w & 0xffff);
105   return p;
106 }
107
108 HaskellObj
109 rts_mkWord32 (HsWord32 w)
110 {
111   /* see rts_mkInt* comments */
112   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
113   p->header.info = W32zh_con_info;
114   p->payload[0]  = (StgClosure *)(StgWord)w;
115   return p;
116 }
117
118 HaskellObj
119 rts_mkWord64 (HsWord64 w)
120 {
121   unsigned long long *tmp;
122
123   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,2));
124   /* see mk_Int8 comment */
125   p->header.info = W64zh_con_info;
126   tmp  = (unsigned long long*)&(p->payload[0]);
127   *tmp = (StgWord64)w;
128   return p;
129 }
130
131 HaskellObj
132 rts_mkFloat (HsFloat f)
133 {
134   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
135   p->header.info = Fzh_con_info;
136   ASSIGN_FLT((P_)p->payload, (StgFloat)f);
137   return p;
138 }
139
140 HaskellObj
141 rts_mkDouble (HsDouble d)
142 {
143   StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,sizeofW(StgDouble)));
144   p->header.info = Dzh_con_info;
145   ASSIGN_DBL((P_)p->payload, (StgDouble)d);
146   return p;
147 }
148
149 HaskellObj
150 rts_mkStablePtr (HsStablePtr s)
151 {
152   StgClosure *p = (StgClosure *)allocate(sizeofW(StgHeader)+1);
153   p->header.info = StablePtr_con_info;
154   p->payload[0]  = (StgClosure *)s;
155   return p;
156 }
157
158 HaskellObj
159 rts_mkPtr (HsPtr a)
160 {
161   StgClosure *p = (StgClosure *)allocate(sizeofW(StgHeader)+1);
162   p->header.info = Ptr_con_info;
163   p->payload[0]  = (StgClosure *)a;
164   return p;
165 }
166
167 #ifdef COMPILER /* GHC has em, Hugs doesn't */
168 HaskellObj
169 rts_mkBool (HsBool b)
170 {
171   if (b) {
172     return (StgClosure *)True_closure;
173   } else {
174     return (StgClosure *)False_closure;
175   }
176 }
177
178 HaskellObj
179 rts_mkString (char *s)
180 {
181   return rts_apply((StgClosure *)unpackCString_closure, rts_mkPtr(s));
182 }
183 #endif /* COMPILER */
184
185 HaskellObj
186 rts_apply (HaskellObj f, HaskellObj arg)
187 {
188   StgAP_UPD *ap = (StgAP_UPD *)allocate(AP_sizeW(1));
189   SET_HDR(ap, &stg_AP_UPD_info, CCS_SYSTEM);
190   ap->n_args = 1;
191   ap->fun    = f;
192   ap->payload[0] = arg;
193   return (StgClosure *)ap;
194 }
195
196 /* ----------------------------------------------------------------------------
197    Deconstructing Haskell objects
198    ------------------------------------------------------------------------- */
199
200 HsChar
201 rts_getChar (HaskellObj p)
202 {
203   if ( p->header.info == Czh_con_info || 
204        p->header.info == Czh_static_info) {
205     return (StgChar)(StgWord)(p->payload[0]);
206   } else {
207     barf("getChar: not a Char");
208   }
209 }
210
211 HsInt
212 rts_getInt (HaskellObj p)
213 {
214   if ( 1 ||
215        p->header.info == Izh_con_info || 
216        p->header.info == Izh_static_info ) {
217     return (int)(p->payload[0]);
218   } else {
219     barf("getInt: not an Int");
220   }
221 }
222
223 HsInt32
224 rts_getInt32 (HaskellObj p)
225 {
226   if ( 1 ||
227        p->header.info == I32zh_con_info || 
228        p->header.info == I32zh_static_info ) {
229     return (int)(p->payload[0]);
230   } else {
231     barf("getInt: not an Int");
232   }
233 }
234
235 HsWord
236 rts_getWord (HaskellObj p)
237 {
238   if ( 1 || /* see above comment */
239        p->header.info == Wzh_con_info ||
240        p->header.info == Wzh_static_info ) {
241     return (unsigned int)(p->payload[0]);
242   } else {
243     barf("getWord: not a Word");
244   }
245 }
246
247 HsWord32
248 rts_getWord32 (HaskellObj p)
249 {
250   if ( 1 || /* see above comment */
251        p->header.info == W32zh_con_info ||
252        p->header.info == W32zh_static_info ) {
253     return (unsigned int)(p->payload[0]);
254   } else {
255     barf("getWord: not a Word");
256   }
257 }
258
259 HsFloat
260 rts_getFloat (HaskellObj p)
261 {
262   if ( p->header.info == Fzh_con_info || 
263        p->header.info == Fzh_static_info ) {
264     return (float)(PK_FLT((P_)p->payload));
265   } else {
266     barf("getFloat: not a Float");
267   }
268 }
269
270 HsDouble
271 rts_getDouble (HaskellObj p)
272 {
273   if ( p->header.info == Dzh_con_info || 
274        p->header.info == Dzh_static_info ) {
275     return (double)(PK_DBL((P_)p->payload));
276   } else {
277     barf("getDouble: not a Double");
278   }
279 }
280
281 HsStablePtr
282 rts_getStablePtr (HaskellObj p)
283 {
284   if ( p->header.info == StablePtr_con_info || 
285        p->header.info == StablePtr_static_info ) {
286     return (StgStablePtr)(p->payload[0]);
287   } else {
288     barf("getStablePtr: not a StablePtr");
289   }
290 }
291
292 HsPtr
293 rts_getPtr (HaskellObj p)
294 {
295   if ( p->header.info == Ptr_con_info || 
296        p->header.info == Ptr_static_info ) {
297     return (void *)(p->payload[0]);
298   } else {
299     barf("getPtr: not an Ptr");
300   }
301 }
302
303 #ifdef COMPILER /* GHC has em, Hugs doesn't */
304 HsBool
305 rts_getBool (HaskellObj p)
306 {
307   if (p == True_closure) {
308     return 1;
309   } else if (p == False_closure) {
310     return 0;
311   } else {
312     barf("getBool: not a Bool");
313   }
314 }
315 #endif /* COMPILER */
316
317 /* ----------------------------------------------------------------------------
318    Evaluating Haskell expressions
319    ------------------------------------------------------------------------- */
320 SchedulerStatus
321 rts_eval (HaskellObj p, /*out*/HaskellObj *ret)
322 {
323   StgTSO *tso = createGenThread(RtsFlags.GcFlags.initialStkSize, p);
324   scheduleThread(tso);
325   return waitThread(tso, ret);
326 }
327
328 SchedulerStatus
329 rts_eval_ (HaskellObj p, unsigned int stack_size, /*out*/HaskellObj *ret)
330 {
331   StgTSO *tso = createGenThread(stack_size, p);
332   scheduleThread(tso);
333   return waitThread(tso, ret);
334 }
335
336 /*
337  * rts_evalIO() evaluates a value of the form (IO a), forcing the action's
338  * result to WHNF before returning.
339  */
340 SchedulerStatus
341 rts_evalIO (HaskellObj p, /*out*/HaskellObj *ret)
342 {
343   StgTSO* tso = createStrictIOThread(RtsFlags.GcFlags.initialStkSize, p);
344   scheduleThread(tso);
345   return waitThread(tso, ret);
346 }
347
348 /*
349  * Like rts_evalIO(), but doesn't force the action's result.
350  */
351 SchedulerStatus
352 rts_evalLazyIO (HaskellObj p, unsigned int stack_size, /*out*/HaskellObj *ret)
353 {
354   StgTSO *tso = createIOThread(stack_size, p);
355   scheduleThread(tso);
356   return waitThread(tso, ret);
357 }
358
359 #if defined(PAR)
360 /*
361   Needed in the parallel world for non-Main PEs, which do not get a piece
362   of work to start with --- they have to humbly ask for it
363 */
364
365 SchedulerStatus
366 rts_evalNothing(unsigned int stack_size)
367 {
368   /* ToDo: propagate real SchedulerStatus back to caller */
369   scheduleThread(END_TSO_QUEUE);
370   return Success;
371 }
372 #endif
373
374 /* Convenience function for decoding the returned status. */
375
376 void
377 rts_checkSchedStatus ( char* site, SchedulerStatus rc )
378 {
379     switch (rc) {
380     case Success:
381         return;
382     case Killed:
383         barf("%s: uncaught exception",site);
384     case Interrupted:
385         barf("%s: interrupted", site);
386     case Deadlock:
387         barf("%s: no threads to run:  infinite loop or deadlock?", site);
388     default:
389         barf("%s: Return code (%d) not ok",(site),(rc));        
390     }
391 }