RtsAPI.c 9.09 KB
Newer Older
1
/* ----------------------------------------------------------------------------
2
 * $Id: RtsAPI.c,v 1.22 2000/11/13 14:40:37 simonmar Exp $
3
 *
4
 * (c) The GHC Team, 1998-2000
5
6
7
8
9
10
11
12
 *
 * API for invoking Haskell functions via the RTS
 *
 * --------------------------------------------------------------------------*/

#include "Rts.h"
#include "Storage.h"
#include "RtsAPI.h"
sof's avatar
sof committed
13
#include "SchedAPI.h"
14
15
#include "RtsFlags.h"
#include "RtsUtils.h"
16
#include "Prelude.h"
17
18
19
20
21

/* ----------------------------------------------------------------------------
   Building Haskell objects from C datatypes.
   ------------------------------------------------------------------------- */
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
28
29
30
  return p;
}

HaskellObj
31
rts_mkInt (HsInt i)
32
33
{
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
34
  p->header.info = Izh_con_info;
35
36
37
38
39
  p->payload[0]  = (StgClosure *)(StgInt)i;
  return p;
}

HaskellObj
40
rts_mkInt8 (HsInt8 i)
41
42
43
44
45
46
{
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
  /* This is a 'cheat', using the static info table for Ints,
     instead of the one for Int8, but the types have identical
     representation.
  */
47
  p->header.info = Izh_con_info;
48
49
50
51
52
53
  /* Make sure we mask out the bits above the lowest 8 */
  p->payload[0]  = (StgClosure *)(StgInt)((unsigned)i & 0xff);
  return p;
}

HaskellObj
54
rts_mkInt16 (HsInt16 i)
55
56
57
58
59
60
{
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
  /* This is a 'cheat', using the static info table for Ints,
     instead of the one for Int8, but the types have identical
     representation.
  */
61
  p->header.info = Izh_con_info;
62
63
64
65
66
67
  /* Make sure we mask out the relevant bits */
  p->payload[0]  = (StgClosure *)(StgInt)((unsigned)i & 0xffff);
  return p;
}

HaskellObj
68
rts_mkInt32 (HsInt32 i)
69
70
71
{
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
  /* see mk_Int8 comment */
72
  p->header.info = Izh_con_info;
73
74
75
76
77
  p->payload[0]  = (StgClosure *)(StgInt)i;
  return p;
}

HaskellObj
78
rts_mkInt64 (HsInt64 i)
79
80
81
82
{
  long long *tmp;
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,2));
  /* see mk_Int8 comment */
83
  p->header.info = I64zh_con_info;
84
85
86
87
88
89
  tmp  = (long long*)&(p->payload[0]);
  *tmp = (StgInt64)i;
  return p;
}

HaskellObj
90
rts_mkWord (HsWord i)
91
92
{
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
93
  p->header.info = Wzh_con_info;
94
95
96
97
98
  p->payload[0]  = (StgClosure *)(StgWord)i;
  return p;
}

HaskellObj
99
rts_mkWord8 (HsWord8 w)
100
101
102
{
  /* see rts_mkInt* comments */
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
103
  p->header.info = Wzh_con_info;
104
105
106
107
108
  p->payload[0]  = (StgClosure *)(StgWord)(w & 0xff);
  return p;
}

HaskellObj
109
rts_mkWord16 (HsWord16 w)
110
111
112
{
  /* see rts_mkInt* comments */
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
113
  p->header.info = Wzh_con_info;
114
115
116
117
118
  p->payload[0]  = (StgClosure *)(StgWord)(w & 0xffff);
  return p;
}

HaskellObj
119
rts_mkWord32 (HsWord32 w)
120
121
122
{
  /* see rts_mkInt* comments */
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
123
  p->header.info = Wzh_con_info;
124
125
126
127
128
  p->payload[0]  = (StgClosure *)(StgWord)w;
  return p;
}

HaskellObj
129
rts_mkWord64 (HsWord64 w)
130
131
132
133
134
{
  unsigned long long *tmp;

  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,2));
  /* see mk_Int8 comment */
135
  p->header.info = W64zh_con_info;
136
  tmp  = (unsigned long long*)&(p->payload[0]);
sof's avatar
sof committed
137
  *tmp = (StgWord64)w;
138
139
140
141
  return p;
}

HaskellObj
142
rts_mkFloat (HsFloat f)
143
144
{
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1));
145
  p->header.info = Fzh_con_info;
146
147
148
149
150
  ASSIGN_FLT((P_)p->payload, (StgFloat)f);
  return p;
}

HaskellObj
151
rts_mkDouble (HsDouble d)
152
153
{
  StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,sizeofW(StgDouble)));
154
  p->header.info = Dzh_con_info;
155
156
157
158
159
  ASSIGN_DBL((P_)p->payload, (StgDouble)d);
  return p;
}

HaskellObj
160
rts_mkStablePtr (HsStablePtr s)
161
162
{
  StgClosure *p = (StgClosure *)allocate(sizeofW(StgHeader)+1);
163
  p->header.info = StablePtr_con_info;
164
165
166
167
168
  p->payload[0]  = (StgClosure *)s;
  return p;
}

HaskellObj
169
rts_mkAddr (HsAddr a)
170
171
{
  StgClosure *p = (StgClosure *)allocate(sizeofW(StgHeader)+1);
172
  p->header.info = Azh_con_info;
173
174
175
176
177
178
  p->payload[0]  = (StgClosure *)a;
  return p;
}

#ifdef COMPILER /* GHC has em, Hugs doesn't */
HaskellObj
179
rts_mkBool (HsBool b)
180
181
{
  if (b) {
182
    return (StgClosure *)True_closure;
183
  } else {
184
    return (StgClosure *)False_closure;
185
186
187
188
189
190
  }
}

HaskellObj
rts_mkString (char *s)
{
191
  return rts_apply((StgClosure *)unpackCString_closure, rts_mkAddr(s));
192
}
193
#endif /* COMPILER */
194
195
196
197
198

HaskellObj
rts_apply (HaskellObj f, HaskellObj arg)
{
  StgAP_UPD *ap = (StgAP_UPD *)allocate(AP_sizeW(1));
199
  SET_HDR(ap, &stg_AP_UPD_info, CCS_SYSTEM);
200
201
  ap->n_args = 1;
  ap->fun    = f;
202
  ap->payload[0] = arg;
203
204
205
206
207
208
209
  return (StgClosure *)ap;
}

/* ----------------------------------------------------------------------------
   Deconstructing Haskell objects
   ------------------------------------------------------------------------- */

210
HsChar
211
212
rts_getChar (HaskellObj p)
{
213
214
  if ( p->header.info == Czh_con_info || 
       p->header.info == Czh_static_info) {
215
    return (StgChar)(StgWord)(p->payload[0]);
216
217
218
219
220
  } else {
    barf("getChar: not a Char");
  }
}

221
HsInt
222
223
rts_getInt (HaskellObj p)
{
sof's avatar
sof committed
224
  if ( 1 ||
225
226
       p->header.info == Izh_con_info || 
       p->header.info == Izh_static_info ) {
sof's avatar
sof committed
227
228
229
230
231
232
    return (int)(p->payload[0]);
  } else {
    barf("getInt: not an Int");
  }
}

233
HsInt32
sof's avatar
sof committed
234
235
236
rts_getInt32 (HaskellObj p)
{
  if ( 1 ||
237
238
       p->header.info == Izh_con_info || 
       p->header.info == Izh_static_info ) {
239
240
241
242
243
244
    return (int)(p->payload[0]);
  } else {
    barf("getInt: not an Int");
  }
}

245
HsWord
246
247
rts_getWord (HaskellObj p)
{
sof's avatar
sof committed
248
  if ( 1 || /* see above comment */
249
250
       p->header.info == Wzh_con_info ||
       p->header.info == Wzh_static_info ) {
251
252
253
254
255
256
    return (unsigned int)(p->payload[0]);
  } else {
    barf("getWord: not a Word");
  }
}

257
HsWord32
sof's avatar
sof committed
258
259
260
rts_getWord32 (HaskellObj p)
{
  if ( 1 || /* see above comment */
261
262
       p->header.info == Wzh_con_info ||
       p->header.info == Wzh_static_info ) {
sof's avatar
sof committed
263
264
265
266
267
268
    return (unsigned int)(p->payload[0]);
  } else {
    barf("getWord: not a Word");
  }
}

269
HsFloat
270
271
rts_getFloat (HaskellObj p)
{
272
273
  if ( p->header.info == Fzh_con_info || 
       p->header.info == Fzh_static_info ) {
274
275
276
277
278
279
    return (float)(PK_FLT((P_)p->payload));
  } else {
    barf("getFloat: not a Float");
  }
}

280
HsDouble
281
282
rts_getDouble (HaskellObj p)
{
283
284
  if ( p->header.info == Dzh_con_info || 
       p->header.info == Dzh_static_info ) {
285
286
287
288
289
290
    return (double)(PK_DBL((P_)p->payload));
  } else {
    barf("getDouble: not a Double");
  }
}

291
HsStablePtr
292
293
rts_getStablePtr (HaskellObj p)
{
294
295
  if ( p->header.info == StablePtr_con_info || 
       p->header.info == StablePtr_static_info ) {
296
297
298
299
300
301
    return (StgStablePtr)(p->payload[0]);
  } else {
    barf("getStablePtr: not a StablePtr");
  }
}

302
HsAddr
303
304
rts_getAddr (HaskellObj p)
{
305
306
  if ( p->header.info == Azh_con_info || 
       p->header.info == Azh_static_info ) {
sof's avatar
sof committed
307
  
308
309
310
311
312
313
314
    return (void *)(p->payload[0]);
  } else {
    barf("getAddr: not an Addr");
  }
}

#ifdef COMPILER /* GHC has em, Hugs doesn't */
315
HsBool
316
317
rts_getBool (HaskellObj p)
{
318
  if (p == True_closure) {
319
    return 1;
320
  } else if (p == False_closure) {
321
    return 0;
322
323
324
325
326
327
328
329
330
331
332
333
334
  } else {
    barf("getBool: not a Bool");
  }
}
#endif /* COMPILER */

/* ----------------------------------------------------------------------------
   Evaluating Haskell expressions
   ------------------------------------------------------------------------- */
SchedulerStatus
rts_eval (HaskellObj p, /*out*/HaskellObj *ret)
{
  StgTSO *tso = createGenThread(RtsFlags.GcFlags.initialStkSize, p);
335
336
  scheduleThread(tso);
  return waitThread(tso, ret);
337
338
339
340
341
342
}

SchedulerStatus
rts_eval_ (HaskellObj p, unsigned int stack_size, /*out*/HaskellObj *ret)
{
  StgTSO *tso = createGenThread(stack_size, p);
343
344
  scheduleThread(tso);
  return waitThread(tso, ret);
345
346
}

sof's avatar
sof committed
347
348
349
350
/*
 * rts_evalIO() evaluates a value of the form (IO a), forcing the action's
 * result to WHNF before returning.
 */
351
352
353
SchedulerStatus
rts_evalIO (HaskellObj p, /*out*/HaskellObj *ret)
{
sof's avatar
sof committed
354
  StgTSO* tso = createStrictIOThread(RtsFlags.GcFlags.initialStkSize, p);
355
356
  scheduleThread(tso);
  return waitThread(tso, ret);
357
358
}

sof's avatar
sof committed
359
360
361
/*
 * Like rts_evalIO(), but doesn't force the action's result.
 */
362
SchedulerStatus
sof's avatar
sof committed
363
rts_evalLazyIO (HaskellObj p, unsigned int stack_size, /*out*/HaskellObj *ret)
364
365
{
  StgTSO *tso = createIOThread(stack_size, p);
366
367
  scheduleThread(tso);
  return waitThread(tso, ret);
368
369
}

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
#if defined(PAR) || defined(SMP)
/*
  Needed in the parallel world for non-Main PEs, which do not get a piece
  of work to start with --- they have to humbly ask for it
*/

SchedulerStatus
rts_evalNothing(unsigned int stack_size)
{
  /* ToDo: propagate real SchedulerStatus back to caller */
  scheduleThread(END_TSO_QUEUE);
  return Success;
}
#endif

385
386
/* Convenience function for decoding the returned status. */

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
void
rts_checkSchedStatus ( char* site, SchedulerStatus rc )
{
    switch (rc) {
    case Success:
	return;
    case Killed:
	barf("%s: uncaught exception",site);
    case Interrupted:
	barf("%s: interrupted", site);
    case Deadlock:
	barf("%s: no threads to run:  infinite loop or deadlock?", site);
    default:
	barf("%s: Return code (%d) not ok",(site),(rc));	
    }
402
}