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