InfoTables.h 12.9 KB
Newer Older
1
/* ----------------------------------------------------------------------------
2
 *
3
 * (c) The GHC Team, 1998-2002
4
 *
5
6
7
8
 * Info Tables
 *
 * -------------------------------------------------------------------------- */

9
#pragma once
10

Simon Marlow's avatar
Simon Marlow committed
11
12
13
14
15
16
/* ----------------------------------------------------------------------------
   Relative pointers

   Several pointer fields in info tables are expressed as offsets
   relative to the info pointer, so that we can generate
   position-independent code.
17
18
19
20
21
22
23
24
25
26
27

   Note [x86-64-relative]
   There is a complication on the x86_64 platform, where pointers are
   64 bits, but the tools don't support 64-bit relative relocations.
   However, the default memory model (small) ensures that all symbols
   have values in the lower 2Gb of the address space, so offsets all
   fit in 32 bits.  Hence we can use 32-bit offset fields.

   Somewhere between binutils-2.16.1 and binutils-2.16.91.0.6,
   support for 64-bit PC-relative relocations was added, so maybe this
   hackery can go away sometime.
Simon Marlow's avatar
Simon Marlow committed
28
29
   ------------------------------------------------------------------------- */

Ben Gamari's avatar
Ben Gamari committed
30
#if defined(x86_64_TARGET_ARCH)
31
#define OFFSET_FIELD(n) StgHalfInt n; StgHalfWord __pad_##n
32
#else
33
#define OFFSET_FIELD(n) StgInt n
Simon Marlow's avatar
Simon Marlow committed
34
35
#endif

36
37
38
39
40
/* -----------------------------------------------------------------------------
   Profiling info
   -------------------------------------------------------------------------- */

typedef struct {
Ben Gamari's avatar
Ben Gamari committed
41
#if !defined(TABLES_NEXT_TO_CODE)
42
43
    char *closure_type;
    char *closure_desc;
Simon Marlow's avatar
Simon Marlow committed
44
45
46
47
#else
    OFFSET_FIELD(closure_type_off);
    OFFSET_FIELD(closure_desc_off);
#endif
48
49
} StgProfInfo;

50
51
52
53
/* -----------------------------------------------------------------------------
   Closure flags
   -------------------------------------------------------------------------- */

54
55
/* The type flags provide quick access to certain properties of a closure. */

56
#define _HNF (1<<0)  /* head normal form?    */
57
#define _BTM (1<<1)  /* uses info->layout.bitmap */
58
#define _NS  (1<<2)  /* non-sparkable        */
Simon Marlow's avatar
Simon Marlow committed
59
60
61
62
63
64
#define _THU (1<<3)  /* thunk?               */
#define _MUT (1<<4)  /* mutable?             */
#define _UPT (1<<5)  /* unpointed?           */
#define _SRT (1<<6)  /* has an SRT?          */
#define _IND (1<<7)  /* is an indirection?   */

65
66
67
68
69
#define isMUTABLE(flags)   ((flags) &_MUT)
#define isBITMAP(flags)    ((flags) &_BTM)
#define isTHUNK(flags)     ((flags) &_THU)
#define isUNPOINTED(flags) ((flags) &_UPT)
#define hasSRT(flags)      ((flags) &_SRT)
70

71
72
extern StgWord16 closure_flags[];

73
74
#define closureFlags(c)         (closure_flags[get_itbl \
                                    (UNTAG_CONST_CLOSURE(c))->type])
75

76
77
#define closure_HNF(c)          (  closureFlags(c) & _HNF)
#define closure_BITMAP(c)       (  closureFlags(c) & _BTM)
78
#define closure_NON_SPARK(c)    ( (closureFlags(c) & _NS))
79
#define closure_SHOULD_SPARK(c) (!(closureFlags(c) & _NS))
80
#define closure_THUNK(c)        (  closureFlags(c) & _THU)
81
82
#define closure_MUTABLE(c)      (  closureFlags(c) & _MUT)
#define closure_UNPOINTED(c)    (  closureFlags(c) & _UPT)
83
#define closure_SRT(c)          (  closureFlags(c) & _SRT)
84
#define closure_IND(c)          (  closureFlags(c) & _IND)
85
86
87

/* same as above but for info-ptr rather than closure */
#define ipFlags(ip)             (closure_flags[ip->type])
88

89
#define ip_HNF(ip)               (  ipFlags(ip) & _HNF)
90
91
92
93
94
95
96
#define ip_BITMAP(ip)            (  ipFlags(ip) & _BTM)
#define ip_SHOULD_SPARK(ip)      (!(ipFlags(ip) & _NS))
#define ip_THUNK(ip)             (  ipFlags(ip) & _THU)
#define ip_MUTABLE(ip)           (  ipFlags(ip) & _MUT)
#define ip_UNPOINTED(ip)         (  ipFlags(ip) & _UPT)
#define ip_SRT(ip)               (  ipFlags(ip) & _SRT)
#define ip_IND(ip)               (  ipFlags(ip) & _IND)
97
98

/* -----------------------------------------------------------------------------
99
100
101
102
103
104
   Bitmaps

   These are used to describe the pointerhood of a sequence of words
   (usually on the stack) to the garbage collector.  The two primary
   uses are for stack frames, and functions (where we need to describe
   the layout of a PAP to the GC).
105
106

   In these bitmaps: 0 == ptr, 1 == non-ptr.
107
108
   -------------------------------------------------------------------------- */

109
/*
110
 * Small bitmaps:  for a small bitmap, we store the size and bitmap in
111
112
113
 * the same word, using the following macros.  If the bitmap doesn't
 * fit in a single word, we use a pointer to an StgLargeBitmap below.
 */
114
115
116
117
#define MK_SMALL_BITMAP(size,bits) (((bits)<<BITMAP_BITS_SHIFT) | (size))

#define BITMAP_SIZE(bitmap) ((bitmap) & BITMAP_SIZE_MASK)
#define BITMAP_BITS(bitmap) ((bitmap) >> BITMAP_BITS_SHIFT)
118

119
120
121
/*
 * A large bitmap.
 */
122
typedef struct {
123
  StgWord size;
124
  StgWord bitmap[];
125
126
} StgLargeBitmap;

127
128
129
/* ----------------------------------------------------------------------------
   Info Tables
   ------------------------------------------------------------------------- */
130

131
132
133
134
135
/*
 * Stuff describing the closure layout.  Well, actually, it might
 * contain the selector index for a THUNK_SELECTOR.  This union is one
 * word long.
 */
136
typedef union {
137
138
139
    struct {                    /* Heap closure payload layout: */
        StgHalfWord ptrs;       /* number of pointers */
        StgHalfWord nptrs;      /* number of non-pointers */
140
    } payload;
141
142
143

    StgWord bitmap;               /* word-sized bit pattern describing */
                                  /*  a stack frame: see below */
144

Ben Gamari's avatar
Ben Gamari committed
145
#if !defined(TABLES_NEXT_TO_CODE)
146
    StgLargeBitmap* large_bitmap; /* pointer to large bitmap structure */
147
#else
148
    OFFSET_FIELD(large_bitmap_offset);  /* offset from info table to large bitmap structure */
149
#endif
150
151

    StgWord selector_offset;      /* used in THUNK_SELECTORs */
sof's avatar
sof committed
152

153
154
155
} StgClosureInfo;


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#if defined(x86_64_TARGET_ARCH) && defined(TABLES_NEXT_TO_CODE)
// On x86_64 we can fit a pointer offset in half a word, so put the SRT offset
// in the info->srt field directly.
#define USE_INLINE_SRT_FIELD
#endif

#if defined(USE_INLINE_SRT_FIELD)
// offset to the SRT / closure, or zero if there's no SRT
typedef StgHalfInt StgSRTField;
#else
// non-zero if there is an SRT, the offset is in the optional srt field.
typedef StgHalfWord StgSRTField;
#endif


171
172
173
/*
 * The "standard" part of an info table.  Every info table has this bit.
 */
Simon Marlow's avatar
Simon Marlow committed
174
typedef struct StgInfoTable_ {
175

176
#if !defined(TABLES_NEXT_TO_CODE)
177
    StgFunPtr       entry;      /* pointer to the entry code */
178
179
#endif

Ben Gamari's avatar
Ben Gamari committed
180
#if defined(PROFILING)
181
    StgProfInfo     prof;
sof's avatar
sof committed
182
#endif
183

184
    StgClosureInfo  layout;     /* closure layout info (one word) */
185

186
    StgHalfWord     type;       /* closure type */
187
    StgSRTField     srt;
188
189
190
       /* In a CONSTR:
            - the constructor tag
          In a FUN/THUNK
191
192
193
194
            - if USE_INLINE_SRT_FIELD
              - offset to the SRT (or zero if no SRT)
            - otherwise
              - non-zero if there is an SRT, offset is in srt_offset
195
       */
196

Ben Gamari's avatar
Ben Gamari committed
197
#if defined(TABLES_NEXT_TO_CODE)
198
    StgCode         code[];
199
#endif
thomie's avatar
thomie committed
200
} *StgInfoTablePtr; // StgInfoTable defined in rts/Types.h
201

202
203
204
205
206
207
208
209
210
211

/* -----------------------------------------------------------------------------
   Function info tables

   This is the general form of function info tables.  The compiler
   will omit some of the fields in common cases:

   -  If fun_type is not ARG_GEN or ARG_GEN_BIG, then the slow_apply
      and bitmap fields may be left out (they are at the end, so omitting
      them doesn't affect the layout).
212

213
   -  If has_srt (in the std info table part) is zero, then the srt
Ben Gamari's avatar
Ben Gamari committed
214
      field needn't be set.  This only applies if the slow_apply and
215
216
217
      bitmap fields have also been omitted.
   -------------------------------------------------------------------------- */

Ben Gamari's avatar
Ben Gamari committed
218
219
220
221
222
223
224
225
226
227
228
/*
   Note [Encoding static reference tables]
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   As static reference tables appear frequently in code, we use a special
   compact encoding for the common case of a module defining only a few CAFs: We
   produce one table containing a list of CAFs in the module and then include a
   bitmap in each info table describing which entries of this table the closure
   references.
 */

Simon Marlow's avatar
Simon Marlow committed
229
typedef struct StgFunInfoExtraRev_ {
230
    OFFSET_FIELD(slow_apply_offset); /* apply to args on the stack */
231
232
233
    union {
        StgWord bitmap;
        OFFSET_FIELD(bitmap_offset);    /* arg ptr/nonptr bitmap */
234
    } b;
235
#if !defined(USE_INLINE_SRT_FIELD)
236
    OFFSET_FIELD(srt_offset);   /* pointer to the SRT closure */
237
#endif
238
239
    StgHalfWord    fun_type;    /* function type */
    StgHalfWord    arity;       /* function arity */
240
241
} StgFunInfoExtraRev;

Simon Marlow's avatar
Simon Marlow committed
242
typedef struct StgFunInfoExtraFwd_ {
243
244
    StgHalfWord    fun_type;    /* function type */
    StgHalfWord    arity;       /* function arity */
245
    StgClosure    *srt;         /* pointer to the SRT closure */
246
    union { /* union for compat. with TABLES_NEXT_TO_CODE version */
247
        StgWord        bitmap;  /* arg ptr/nonptr bitmap */
248
    } b;
249
    StgFun         *slow_apply; /* apply to args on the stack */
250
251
252
253
254
255
256
257
258
} StgFunInfoExtraFwd;

typedef struct {
#if defined(TABLES_NEXT_TO_CODE)
    StgFunInfoExtraRev f;
    StgInfoTable i;
#else
    StgInfoTable i;
    StgFunInfoExtraFwd f;
259
260
261
#endif
} StgFunInfoTable;

262
// canned bitmap for each arg type, indexed by constants in FunTypes.h
263
extern const StgWord stg_arg_bitmaps[];
264

265
266
267
268
/* -----------------------------------------------------------------------------
   Return info tables
   -------------------------------------------------------------------------- */

269
270
/*
 * When info tables are laid out backwards, we can omit the SRT
271
 * pointer iff has_srt is zero.
272
 */
273

274
typedef struct {
275
#if defined(TABLES_NEXT_TO_CODE)
276
#if !defined(USE_INLINE_SRT_FIELD)
277
    OFFSET_FIELD(srt_offset);   /* offset to the SRT closure */
278
#endif
279
    StgInfoTable i;
280
281
#else
    StgInfoTable i;
282
    StgClosure  *srt;           /* pointer to the SRT closure */
283
284
285
286
287
288
289
#endif
} StgRetInfoTable;

/* -----------------------------------------------------------------------------
   Thunk info tables
   -------------------------------------------------------------------------- */

290
291
/*
 * When info tables are laid out backwards, we can omit the SRT
292
 * pointer iff has_srt is zero.
293
 */
294

Simon Marlow's avatar
Simon Marlow committed
295
typedef struct StgThunkInfoTable_ {
296
#if defined(TABLES_NEXT_TO_CODE)
297
#if !defined(USE_INLINE_SRT_FIELD)
298
    OFFSET_FIELD(srt_offset);   /* offset to the SRT closure */
299
#endif
300
    StgInfoTable i;
301
302
303
#else
    StgInfoTable i;
    StgClosure  *srt;           /* pointer to the SRT closure */
304
#endif
305
} StgThunkInfoTable;
306

307
308
309
310
/* -----------------------------------------------------------------------------
   Constructor info tables
   -------------------------------------------------------------------------- */

Simon Marlow's avatar
Simon Marlow committed
311
typedef struct StgConInfoTable_ {
312
313
314
315
#if !defined(TABLES_NEXT_TO_CODE)
    StgInfoTable i;
#endif

316
#if defined(TABLES_NEXT_TO_CODE)
317
    OFFSET_FIELD(con_desc); // the name of the data constructor
318
                            // as: Package:Module.Name
319
320
#else
    char *con_desc;
Simon Marlow's avatar
Simon Marlow committed
321
#endif
322
323
324
325
326
327

#if defined(TABLES_NEXT_TO_CODE)
    StgInfoTable i;
#endif
} StgConInfoTable;

328
329
330
331
332

/* -----------------------------------------------------------------------------
   Accessor macros for fields that might be offsets (C version)
   -------------------------------------------------------------------------- */

333
334
335
336
/*
 * GET_SRT(info)
 * info must be a Stg[Ret|Thunk]InfoTable* (an info table that has a SRT)
 */
Ben Gamari's avatar
Ben Gamari committed
337
#if defined(TABLES_NEXT_TO_CODE)
338
#if x86_64_TARGET_ARCH
339
#define GET_SRT(info) \
340
  ((StgClosure*) (((StgWord) ((info)+1)) + (info)->i.srt))
341
#else
342
343
344
345
#define GET_SRT(info) \
  ((StgClosure*) (((StgWord) ((info)+1)) + (info)->srt_offset))
#endif
#else // !TABLES_NEXT_TO_CODE
346
347
348
#define GET_SRT(info) ((info)->srt)
#endif

349
350
351
352
/*
 * GET_CON_DESC(info)
 * info must be a StgConInfoTable*.
 */
Ben Gamari's avatar
Ben Gamari committed
353
#if defined(TABLES_NEXT_TO_CODE)
354
355
#define GET_CON_DESC(info) \
            ((const char *)((StgWord)((info)+1) + (info->con_desc)))
356
#else
357
#define GET_CON_DESC(info) ((const char *)(info)->con_desc)
358
359
#endif

360
361
362
363
/*
 * GET_FUN_SRT(info)
 * info must be a StgFunInfoTable*
 */
Ben Gamari's avatar
Ben Gamari committed
364
#if defined(TABLES_NEXT_TO_CODE)
365
366
367
368
#if x86_64_TARGET_ARCH
#define GET_FUN_SRT(info) \
  ((StgClosure*) (((StgWord) ((info)+1)) + (info)->i.srt))
#else
369
370
#define GET_FUN_SRT(info) \
  ((StgClosure*) (((StgWord) ((info)+1)) + (info)->f.srt_offset))
371
#endif
372
373
374
375
#else
#define GET_FUN_SRT(info) ((info)->f.srt)
#endif

Ben Gamari's avatar
Ben Gamari committed
376
#if defined(TABLES_NEXT_TO_CODE)
377
378
379
380
381
382
#define GET_LARGE_BITMAP(info) ((StgLargeBitmap*) (((StgWord) ((info)+1)) \
                                        + (info)->layout.large_bitmap_offset))
#else
#define GET_LARGE_BITMAP(info) ((info)->layout.large_bitmap)
#endif

Ben Gamari's avatar
Ben Gamari committed
383
#if defined(TABLES_NEXT_TO_CODE)
384
#define GET_FUN_LARGE_BITMAP(info) ((StgLargeBitmap*) (((StgWord) ((info)+1)) \
385
                                        + (info)->f.b.bitmap_offset))
386
#else
387
#define GET_FUN_LARGE_BITMAP(info) ((StgLargeBitmap*) ((info)->f.b.bitmap))
388
389
#endif

Simon Marlow's avatar
Simon Marlow committed
390
391
392
/*
 * GET_PROF_TYPE, GET_PROF_DESC
 */
Ben Gamari's avatar
Ben Gamari committed
393
#if defined(TABLES_NEXT_TO_CODE)
Simon Marlow's avatar
Simon Marlow committed
394
395
396
397
#define GET_PROF_TYPE(info) ((char *)((StgWord)((info)+1) + (info->prof.closure_type_off)))
#else
#define GET_PROF_TYPE(info) ((info)->prof.closure_type)
#endif
Ben Gamari's avatar
Ben Gamari committed
398
#if defined(TABLES_NEXT_TO_CODE)
Simon Marlow's avatar
Simon Marlow committed
399
400
401
402
#define GET_PROF_DESC(info) ((char *)((StgWord)((info)+1) + (info->prof.closure_desc_off)))
#else
#define GET_PROF_DESC(info) ((info)->prof.closure_desc)
#endif