[project @ 2001-08-03 16:30:13 by sof]
[ghc-hetmet.git] / ghc / rts / RtsAPI.c
1 /* ----------------------------------------------------------------------------
2  * $Id: RtsAPI.c,v 1.27 2001/08/03 16:30:13 sof 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("rts_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 (HsInt)(p->payload[0]);
218   } else {
219     barf("rts_getInt: not an Int");
220   }
221 }
222
223 HsInt8
224 rts_getInt8 (HaskellObj p)
225 {
226   if ( 1 ||
227        p->header.info == I8zh_con_info || 
228        p->header.info == I8zh_static_info ) {
229     return (HsInt8)(HsInt)(p->payload[0]);
230   } else {
231     barf("rts_getInt8: not an Int8");
232   }
233 }
234
235 HsInt16
236 rts_getInt16 (HaskellObj p)
237 {
238   if ( 1 ||
239        p->header.info == I16zh_con_info || 
240        p->header.info == I16zh_static_info ) {
241     return (HsInt16)(HsInt)(p->payload[0]);
242   } else {
243     barf("rts_getInt16: not an Int16");
244   }
245 }
246
247 HsInt32
248 rts_getInt32 (HaskellObj p)
249 {
250   if ( 1 ||
251        p->header.info == I32zh_con_info || 
252        p->header.info == I32zh_static_info ) {
253     return (HsInt32)(p->payload[0]);
254   } else {
255     barf("rts_getInt32: not an Int32");
256   }
257 }
258
259 HsInt64
260 rts_getInt64 (HaskellObj p)
261 {
262   HsInt64* tmp;
263   if ( 1 ||
264        p->header.info == I64zh_con_info || 
265        p->header.info == I64zh_static_info ) {
266     tmp = (HsInt64*)&(p->payload[0]);
267     return *tmp;
268   } else {
269     barf("rts_getInt64: not an Int64");
270   }
271 }
272 HsWord
273 rts_getWord (HaskellObj p)
274 {
275   if ( 1 || /* see above comment */
276        p->header.info == Wzh_con_info ||
277        p->header.info == Wzh_static_info ) {
278     return (HsWord)(p->payload[0]);
279   } else {
280     barf("rts_getWord: not a Word");
281   }
282 }
283
284 HsWord8
285 rts_getWord8 (HaskellObj p)
286 {
287   if ( 1 || /* see above comment */
288        p->header.info == W8zh_con_info ||
289        p->header.info == W8zh_static_info ) {
290     return (HsWord8)(HsWord)(p->payload[0]);
291   } else {
292     barf("rts_getWord8: not a Word8");
293   }
294 }
295
296 HsWord16
297 rts_getWord16 (HaskellObj p)
298 {
299   if ( 1 || /* see above comment */
300        p->header.info == W16zh_con_info ||
301        p->header.info == W16zh_static_info ) {
302     return (HsWord16)(HsWord)(p->payload[0]);
303   } else {
304     barf("rts_getWord16: not a Word16");
305   }
306 }
307
308 HsWord32
309 rts_getWord32 (HaskellObj p)
310 {
311   if ( 1 || /* see above comment */
312        p->header.info == W32zh_con_info ||
313        p->header.info == W32zh_static_info ) {
314     return (unsigned int)(p->payload[0]);
315   } else {
316     barf("rts_getWord: not a Word");
317   }
318 }
319
320
321 HsWord64
322 rts_getWord64 (HaskellObj p)
323 {
324   HsWord64* tmp;
325   if ( 1 || /* see above comment */
326        p->header.info == W64zh_con_info ||
327        p->header.info == W64zh_static_info ) {
328     tmp = (HsWord64*)&(p->payload[0]);
329     return *tmp;
330   } else {
331     barf("rts_getWord64: not a Word64");
332   }
333 }
334
335 HsFloat
336 rts_getFloat (HaskellObj p)
337 {
338   if ( p->header.info == Fzh_con_info || 
339        p->header.info == Fzh_static_info ) {
340     return (float)(PK_FLT((P_)p->payload));
341   } else {
342     barf("rts_getFloat: not a Float");
343   }
344 }
345
346 HsDouble
347 rts_getDouble (HaskellObj p)
348 {
349   if ( p->header.info == Dzh_con_info || 
350        p->header.info == Dzh_static_info ) {
351     return (double)(PK_DBL((P_)p->payload));
352   } else {
353     barf("rts_getDouble: not a Double");
354   }
355 }
356
357 HsStablePtr
358 rts_getStablePtr (HaskellObj p)
359 {
360   if ( p->header.info == StablePtr_con_info || 
361        p->header.info == StablePtr_static_info ) {
362     return (StgStablePtr)(p->payload[0]);
363   } else {
364     barf("rts_getStablePtr: not a StablePtr");
365   }
366 }
367
368 HsPtr
369 rts_getPtr (HaskellObj p)
370 {
371   if ( p->header.info == Ptr_con_info || 
372        p->header.info == Ptr_static_info ) {
373     return (void *)(p->payload[0]);
374   } else {
375     barf("rts_getPtr: not an Ptr");
376   }
377 }
378
379 #ifdef COMPILER /* GHC has em, Hugs doesn't */
380 HsBool
381 rts_getBool (HaskellObj p)
382 {
383   if (p == True_closure) {
384     return 1;
385   } else if (p == False_closure) {
386     return 0;
387   } else {
388     barf("rts_getBool: not a Bool");
389   }
390 }
391 #endif /* COMPILER */
392
393 /* ----------------------------------------------------------------------------
394    Evaluating Haskell expressions
395    ------------------------------------------------------------------------- */
396 SchedulerStatus
397 rts_eval (HaskellObj p, /*out*/HaskellObj *ret)
398 {
399   StgTSO *tso = createGenThread(RtsFlags.GcFlags.initialStkSize, p);
400   scheduleThread(tso);
401   return waitThread(tso, ret);
402 }
403
404 SchedulerStatus
405 rts_eval_ (HaskellObj p, unsigned int stack_size, /*out*/HaskellObj *ret)
406 {
407   StgTSO *tso = createGenThread(stack_size, p);
408   scheduleThread(tso);
409   return waitThread(tso, ret);
410 }
411
412 /*
413  * rts_evalIO() evaluates a value of the form (IO a), forcing the action's
414  * result to WHNF before returning.
415  */
416 SchedulerStatus
417 rts_evalIO (HaskellObj p, /*out*/HaskellObj *ret)
418 {
419   StgTSO* tso = createStrictIOThread(RtsFlags.GcFlags.initialStkSize, p);
420   scheduleThread(tso);
421   return waitThread(tso, ret);
422 }
423
424 /*
425  * Like rts_evalIO(), but doesn't force the action's result.
426  */
427 SchedulerStatus
428 rts_evalLazyIO (HaskellObj p, unsigned int stack_size, /*out*/HaskellObj *ret)
429 {
430   StgTSO *tso = createIOThread(stack_size, p);
431   scheduleThread(tso);
432   return waitThread(tso, ret);
433 }
434
435 /* Convenience function for decoding the returned status. */
436
437 void
438 rts_checkSchedStatus ( char* site, SchedulerStatus rc )
439 {
440     switch (rc) {
441     case Success:
442         return;
443     case Killed:
444         barf("%s: uncaught exception",site);
445     case Interrupted:
446         barf("%s: interrupted", site);
447     case Deadlock:
448         barf("%s: no threads to run:  infinite loop or deadlock?", site);
449     default:
450         barf("%s: Return code (%d) not ok",(site),(rc));        
451     }
452 }