Rune - Change regsave burden for syscalls
[rune.git] / librune / type.h
1 /*
2  * TYPE.H
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  *
7  * See libsupport/coretype.h for definitions of runesize_t and a few others.
8  */
9 #ifndef _LIBRUNE_TYPE_H_
10 #define _LIBRUNE_TYPE_H_
11
12 struct Exp;
13 struct Stmt;
14 struct SemGroup;
15 struct Type;
16
17 /*
18  * These are used everywhere but the structure definitions are more
19  * localized.
20  */
21 struct RunContext;
22 struct GenContext;
23 struct RuneThread;
24 struct RuneLock;
25 struct RefStor;
26 typedef struct RunContext *runctx_p;
27 typedef struct GenContext *genctx_p;
28
29 /*
30  * PointerInfo - This structure is typically stored as part of the RefStor
31  *               or stack context.  It contains the auxillary data needed to
32  *               validate a pointer.
33  *
34  *               Auxillary data is essentially static and the code generator
35  *               can cache bits and pieces of it as necessary.  The s_Info
36  *               pointer itself may change when the pointer is reassigned,
37  *               but does not change for nominal pointer arithmatic within
38  *               the pointer's current domain.
39  *
40  *               in_Beg and in_End are only used for PCheck operations and
41  *               may require a dynamic info structure, which is not usually
42  *               implemented.  All info structures are taken from the
43  *               type's static ty_Info template.
44  *
45  * PointerStor - This structure represents a pointer, consisting of the
46  *               actual pointer and a secondary pointer to the related
47  *               info structure.
48  *
49  * LValueStor  - This structure represents an LValue and is essentially the
50  *               same format as a PointerStor now, but we treat it separately
51  *               to reduce confusion.  Unlike pointers, the pointer embedded
52  *               in an LValueStor cannot change and has already been validated.
53  *
54  * NOTE: PointerInfo.s_Type is the pointer target type, not the pointer type.
55  *
56  * WARNING: These structures are hard-coded in various places.
57  */
58 typedef struct PointerInfo {
59         struct RefStor  *in_RefStor;
60         char    *in_Beg;        /* (only for pointer tracking) */
61         char    *in_End;        /* (only for pointer tracking) */
62         struct Type *in_Type;   /* pointer TARGET type */
63         void    **in_DynVec;    /* broken-out of the type */
64         struct PointerInfo *in_Next;
65         runesize_t in_Refs;
66 } PointerInfo;
67
68 #define PINFO_STATIC            ((runesize_t)0x00000001)
69 #define PINFO_INCR              ((runesize_t)0x00000002)
70
71 /*
72  * NOTE: s_Info->in_Type is the type of the object pointed to by s_Addr.
73  *       That is, the pointer target type, not the pointer type.
74  */
75 typedef struct PointerStor {
76         char    *s_Addr;        /* The actual pointer */
77         PointerInfo *s_Info;    /* Auxillary information */
78 } __aligned(16) PointerStor;
79
80 #define SIZE_SIZE               ((runesize_t)(sizeof(runesize_t)))
81 #define CPOINTER_SIZE           ((runesize_t)(sizeof(void *)))
82 #define CPOINTER_ALIGN          ((runesize_t)(CPOINTER_SIZE - 1))
83 #define POINTERINFO_SIZE        ((runesize_t)(sizeof(PointerInfo)))
84 #define POINTERSTOR_SIZE        ((runesize_t)(sizeof(PointerStor)))
85 #define LVALUESTOR_SIZE         ((runesize_t)(sizeof(LValueStor)))
86 #define POINTERSTOR_ALIGN       ((runesize_t)(sizeof(PointerStor) - 1))
87 #define LVALUESTOR_ALIGN        ((runesize_t)(sizeof(LValueStor) - 1))
88
89 #define EXTRA_INTERNAL_SPACE    (CPOINTER_SIZE * 6)
90
91 #define RUNE_PTRSTOR_ADDR       offsetof(PointerStor, s_Addr)
92 #define RUNE_PTRSTOR_INFO       offsetof(PointerStor, s_Info)
93 #define RUNE_LVSTOR_ADDR        offsetof(LValueStor, s_Addr)
94 #define RUNE_LVSTOR_INFO        offsetof(LValueStor, s_Info)
95
96 #define RUNE_PINFO_REFSTOR      offsetof(PointerInfo, in_RefStor)
97 #define RUNE_PINFO_BEG          offsetof(PointerInfo, in_Beg)
98 #define RUNE_PINFO_END          offsetof(PointerInfo, in_End)
99 #define RUNE_PINFO_TYPE         offsetof(PointerInfo, in_Type)
100 #define RUNE_PINFO_DYNVEC       offsetof(PointerInfo, in_DynVec)
101
102 /*
103  * LValueStor
104  *
105  * This structure is the run-time representation of an lvalue object.  It
106  * is typically used to present lvalue arguments and return values for method
107  * calls but may also represent special storage mechanics such as "heap"
108  * and "persist", as well as interpreter-related objects.
109  *
110  * LValue objects are always considered to be valid.  They are not pointers
111  * in that their s_Addr cannot be changed, and the s_Info structure always
112  * points to the type's static ty_Info (in_Beg and in_End are always NULL).
113  *
114  * NOTE: s_Info->in_Type is the type of the object pointed to by s_Addr.
115  *       That is, the target type (which is also how PointerStor works).
116  */
117 typedef struct LValueStor {
118         void    *s_Addr;        /* the actual pointer */
119         PointerInfo *s_Info;    /* Auxillary information */
120 } __aligned(16) LValueStor;
121
122 /*
123  * Interpreter's temporary storage structure.
124  *
125  * Note, however, that an exp should never store more data into the
126  * RunTmpStor than it's ex_Type says it can because higher level calls
127  * (like InterpCompoundExp()) will attempt to avoid copies by directly
128  * passing the destination storage as the TmpStor.
129  *
130  * NOTE: Expression-temporaries never store LValueStor's, which are entities
131  *       that can exist in SemGroups.  The type's SF_LVALUE flag is not
132  *       related to the LValueStor structure.
133  */
134 typedef union RunTmpStor {
135         d_bool_t        ts_Bool;
136         int8_t          ts_Int8;
137         int16_t         ts_Int16;
138         int32_t         ts_Int32;
139         runesize_t      ts_Size;
140         int64_t         ts_Int64;
141         int64_t         ts_Int64Ary[2];
142         d_off_t         ts_Off;
143         u_int8_t        ts_UInt8;
144         u_int16_t       ts_UInt16;
145         u_int32_t       ts_UInt32;
146         u_int64_t       ts_UInt64;
147         u_int64_t       ts_UInt64Ary[2];
148         float           ts_Float32;
149         double          ts_Float64;
150         long double     ts_Float128;
151         PointerStor     ts_Pointer;
152         void            *ts_VoidPtr;
153         void            *ts_CPtr;
154 } RunTmpStor;
155
156 /*
157  * Data element for interpreter.  Note that the data pointer itself is
158  * returned directly as a return value as a means of maintaining high
159  * interpreter performance.  Callers must reassociate the data pointer with
160  * the data object upon return prior to making any calls to data-centric
161  * support routines.  This allows low-level operators to mostly ignore
162  * RunData when operating on basic data.
163  *
164  * mrs          - Sideband ref on the memory containing the object.
165  *
166  * Non-temporary objects remain valid when discarded. Their content is
167  * only dereferenced when they are content-dropped by other means.
168  * Temporaries are always content-dropped when discarded.
169  */
170 typedef struct RunData {
171         void            *data;
172         struct RefStor  *mrs;
173         union {
174                 uint32_t rollup;
175                 struct {
176                         int8_t  istmp;
177                         int8_t  storage;
178                         int8_t  unused02;
179                         int8_t  isdcopy;
180                 };
181         };
182         RunTmpStor      ts;
183 } rundata_t;
184
185 static __inline
186 void
187 rundata_clear(rundata_t *data)
188 {
189         data->data = NULL;
190         data->mrs = NULL;
191         data->rollup = 0;
192 }
193
194 static __inline
195 void
196 rundata_copy(rundata_t *src, void *ptr, rundata_t *dst)
197 {
198         dst->data = ptr;
199         dst->mrs = src->mrs;
200         dst->rollup = src->rollup;
201         if (ptr == &src->ts) {
202                 bcopy(&src->ts, &dst->ts, sizeof(src->ts));
203                 dst->data = &dst->ts;
204         }
205 }
206
207 /*
208  * Data element for code generator.
209  *
210  * minfo        - Sideband info for the storage containing the object,
211  *                typically needed when evaluating lvalue objects and
212  *                &object.
213  * rssg         - Static generation semgroup so static address output can
214  *                figure out the correct info reference.
215  *
216  * Non-temporary objects remain valid when discarded. Their content is
217  * only dereferenced when they are content-dropped by other means.
218  * Temporaries are always content-dropped when discarded.
219  */
220 typedef struct GenData {
221         uint32_t        regno;
222         uint8_t         eamode;
223         uint8_t         storage;
224         uint8_t         istmp;
225         uint8_t         unused03;
226         char            *label;
227         int64_t         offset;         /* also used for immediate value */
228         int64_t         immhi;          /* if 128-bit immediate */
229
230         /*
231          * s_Beg, s_End used by the generator's global data init
232          * during interpretation to calculate relative offsets of
233          * ps->s_Beg and ps->s_End for global pointer initialization.
234          */
235         runesize_t      s_Beg;          /* (generator global data init only) */
236         runesize_t      s_End;          /* (generator global data init only) */
237
238         /*
239          * implied_mask is a bitmask for up to the first 64 LValueStor's
240          * (SCOPE_LVALUE elements) of a compound type, or of a
241          * SCOPE_LVALUE type (such as a lvalue return).  If a bit is
242          * set it indicates that the lvalue element has an implied lock
243          * and should not be LVPUT/LVREL'd on drop.
244          *
245          * We can do this optimization for lvalue elements because the
246          * caller is not allowed to modify the lvs->s_RefStor itself,
247          * and will separately ref/lock any copy it makes.  Such situations
248          * are strictly temporary so the original code setting the bits
249          * knows the content will be done when it disposes of them.
250          * And because of that, implied locks can be chained.
251          */
252         uint64_t        implied_mask;   /* implied locks on LVALUEs */
253
254         void            *cache_id;      /* non-NULL means cacheable */
255         struct Type     *load_type;     /* for memory load/store only */
256         struct GenData  *minfo;         /* sideband PointerInfo on memory */
257         struct GenData  *type;          /* extracted Type, NULL if not dyn */
258         struct SemGroup *rssg;          /* list of decls */
259 } gendata_t;
260
261 typedef gendata_t *gendata_p;
262
263 #define EA_UNKNOWN      0
264 #define EA_DIRECT       1
265 #define EA_MEMORY       2
266 #define EA_UNUSED03     3
267 #define EA_IMMEDIATE    4
268 #define EA_IMMEDIATE16  5               /* 128-bit immediate */
269 #define EA_BAD          0x80U
270
271 /*
272  * The storage fields above represent the nominal storage mode for
273  * the target content of an object, not the memory containing the object.
274  * It is only applicable to references, pointers, lvalues, and compound
275  * types (and only recurses via compound types).  The storage mode for
276  * elements making up e.g. class objects are governed by the class's
277  * declarations.
278  *
279  * For a pointer or reference, for example, 'storage' represents how
280  * the target object represented by PointerStor.s_Info is lock+refd,
281  * not how the memory containing the pointer is lock+refd, or how each
282  * element of a compound type is handled recursively for compound types.
283  *
284  * However, the storage field does NOT classify the elements of a structure.
285  * it strictly classifies only the 'top' element.  A pointer or reference
286  * is different from a structure containing a pointer or reference.
287  *
288  * LValues are a bit more confusing.  An LValue's 'storage' specification
289  * represents how its LValueStor.s_Info is lock+refd and nothing more.
290  * If the LValue represents a pointer/reference type then it is an
291  * LValueStor that points to a PointerStor, but the lock+refd mode of the
292  * PointerStor's target is NOT determined by the 'storage' specification.
293  *
294  * If an LValueStor represents a compound type (verses a pointer to a compound
295  * type), the storage specification recurses as per normal for compound types.
296  *
297  * In method calls, the LValue object is an LValueStor that points to
298  * the object, NOT an LValueStor that pointers to a PointerStor.  It is
299  * NOT a pointer semantically.  Hence why method procedures access the
300  * object using dot notation, as in 'this.BLAH'.
301  *
302  * DEFAULT STORAGE MODES:
303  *      Method target objects   GENSTAT_LOCKH (default)
304  *                              GENSTAT_LOCK  ('soft')
305  *                              GENSTAT_NONE  ('untracked') (note 1)
306  *      Procedure arguments     GENSTAT_ARGDEF (note 2)
307  *      Procedure return        GENSTAT_RETDEF (note 2)
308  *      local variables         GENSTAT_STKDEF (note 2)
309  *      expression temporaries  GENSTAT_EXPDEF
310  *      structural elements     GENSTAT_MEMDEF (note 3)
311  *      compound types          (recursion for passed-in storage mode)
312  *
313  *      note 1 - In untracked mode no refs or locks are obtained.  Untracked
314  *               pointers cannot be cast (as this required a sideband info
315  *               structure).
316  *
317  *      note 2 - If the address is taken of an element or the element is
318  *               used as an lvalue it needs to be GENSTAT_REFD (XXX)
319  *
320  *      note 3 - For maximum compatibility, structural elements are
321  *               GENSTAT_REFD.  The 'storage' field for a class object
322  *               is not applicable (its only applicable for pointers,
323  *               references, and lvalues).
324  *
325  * NONE         Nominal storage status is nothing.
326  * REFD         Nominal storage status is REFD.
327  * LOCK         Nominal storage status is LOCK+REFD.
328  * LOCKH        Nominal storage status is LOCK+REFD using a hard lock.
329  *
330  * EMPTY        (flag) indicates no prior contents to storage, allows
331  *              unnecessary PUTs(etc) to be optimized out.
332  */
333 #define GENSTAT_NONE    0
334 #define GENSTAT_REFD    1
335 #define GENSTAT_LOCK    2
336 #define GENSTAT_LOCKH   3
337 #define GENSTAT_UNSPEC  4       /* when storage mode not known */
338
339 #define GENSTATF_EMPTY  0x10
340
341 #define GENSTAT_EXPDEF  GENSTAT_NONE    /* expression temporaries */
342 #define GENSTAT_ARGDEF  GENSTAT_NONE    /* argument declarations */
343 #define GENSTAT_RETDEF  GENSTAT_NONE    /* return declaration */
344 #define GENSTAT_STKDEF  GENSTAT_NONE    /* local declarations */
345 #define GENSTAT_MEMDEF  GENSTAT_REFD    /* nominal memory */
346 #define GENSTAT_METDEF  GENSTAT_LOCKH   /* method object */
347 #define GENSTAT_ARYDEF  GENSTAT_REFD    /* array elements */
348 #define GENSTAT_TYPDEF  GENSTAT_NONE    /* type default initialization */
349
350 #define REGF_PTR        0x80000000U
351 #define REGF_MASK       0x00FFFFFFU
352 #define REGF_USRMASK    0x7F000000U
353 #define REGF_USRBASE    0x01000000U
354
355 #define REG_FIRSTTMP    100
356
357 #define REG_NEWDAT      ((uint32_t)-1 & REGF_MASK)
358 #define REG_NEWPTR      (REGF_PTR | ((uint32_t)-1 & REGF_MASK))
359
360 #define REG_SG          (REGF_PTR | 9)  /* semgroup pointer (varargs calls) */
361 #define REG_RP          (REGF_PTR | 10) /* return data pointer */
362 #define REG_DB          (REGF_PTR | 11) /* data & module base */
363 #define REG_TP          (REGF_PTR | 12) /* thread pointer */
364 #define REG_AP          (REGF_PTR | 13) /* argument pointer */
365 #define REG_FP          (REGF_PTR | 14) /* frame pointer */
366 #define REG_PC          (REGF_PTR | 15) /* program counter */
367
368 #define REG_ZERO        0
369 #define REG_NULL        (REGF_PTR | 0)
370 #define REG_ABS         REG_NULL
371
372 /*
373  * Branch label element for code generator
374  */
375 typedef struct {
376         genctx_p        ct;     /* (for accounting only) */
377         int32_t         id;
378         int32_t         unused01;
379         runesize_t      bytes;  /* string constants only */
380 } genlabel_t;
381
382 typedef genlabel_t *genlabel_p;
383
384 /*
385  * Type - the type structure.  Types are various forms of instantiated
386  *                              objects.
387  *
388  *      (note 1) - TY_DYNAMIC types are special.  During run-time an
389  *                 expression that normally returns a dynamic type must
390  *                 either be cast to the type you want (which is hinted
391  *                 into exp->ex_Type, replacing the dynamic type), or
392  *                 it must be marked as returning a type.  
393  *
394  *                 Normally a returned type is simply stored in ex_Type,
395  *                 but this doesn't work when making run-time changes
396  *                 (due to reusing the Exp's in a threaded environment).
397  *                 In this case the expression leaves ex_Type set to
398  *                 a TY_DYNAMIC type and will return a pointer to
399  *                 the type as data.
400  *
401  *
402  *      (note 2) - The visibility of a type's contents is set in
403  *                 resolveType() and based on where the type's base
404  *                 class or compound type was defined vs where it
405  *                 is referenced.
406  *
407  * WARNING: Must match classes/sys/runtime.d
408  */
409 struct Type;
410 typedef RUNE_HEAD(typelist, Type) typelist_t;
411
412 typedef struct Type {
413         RUNE_ENTRY(Type) ty_Node;
414         typelist_t      ty_QList;       /* qualified type (ptr-to, etc...) */
415         int             ty_Op;          /* type opcode (TY_*)   */
416         int             ty_Flags;       /* type flags (must be int) */
417         runesize_t      ty_Bytes;       /* size of type in bytes */
418         runesize_t      ty_AlignMask;   /* alignment mask */
419         int             ty_SQFlags;     /* qualifiers, if any */
420         int             ty_Visibility;  /* visib of type's contents (note 2) */
421         typelist_t      *ty_SQList;     /* qualifications list (shared) */
422         struct Exp      *ty_AssExp;     /* assigned default for type */
423         runesize_t      ty_TmpBytes;    /* temporary required for assignment */
424         runesize_t      ty_TmpAlignMask;/* temporary space alignment mask */
425         void            **ty_DynamicVector; /* placeholder for generator */
426         PointerInfo     ty_Info;        /* info template for NULL pointer */
427         union {
428                 struct {
429                         struct SemGroup *et_SemGroup;   /* list of decls */
430                         struct Type *et_Super;          /* superclass */
431                 } ClassType;
432                 struct {
433                         struct SemGroup *et_SemGroup;   /* list of decls */
434                 } ImportType;
435                 struct {
436                         struct Type *et_Type;           /* pointer to type */
437                 } PtrType;
438                 struct {
439                         struct SemGroup *et_SemGroup;   /* for sem search */
440                         struct Exp *et_ArySize;         /* size exp or NULL */
441                         struct Type *et_Type;           /* array of this type */
442                         runesize_t et_Count;            /* resolved elements */
443                 } AryType;
444                 struct {
445                         struct SemGroup *et_SemGroup;   /* list of decls */
446                 } CompType;
447                 struct {
448                         struct SemGroup *et_SemGroup;   /* list of decls */
449                         struct Type *et_Type;           /* type to extend */
450                 } VarType;
451                 struct {
452                         struct Type *et_ArgsType;       /* args (compound) */
453                         struct Type *et_RetType;        /* return type */
454                         runesize_t et_ArgCount;         /* # of args */
455                 } ProcType;
456                 struct {
457                         runesize_t      et_Bytes;       /* size in bytes */
458                 } StorType;
459                 struct {
460                         runesize_t      et_Unused00;
461                 } DynamicType;
462                 struct {
463                         string_t        *et_DottedId;   /* a, b, c, NULL */
464                         struct SemGroup *et_SemGroup;   /* for sem search */
465                         struct SemGroup *et_ImportSemGroup; /* for sem search */
466                 } UnresType;
467                 struct {
468                         void            *et_Fill0;
469                         void            *et_Fill1;
470                         void            *et_Fill2;
471                         void            *et_Fill3;
472                 } FILLER;
473         } u;
474 } Type;
475
476 #define RUNE_TYPE_DYNAMIC_VECTOR        \
477                 ((runesize_t)offsetof(Type, ty_DynamicVector))
478 #define RUNE_TYPE_INFO                  \
479                 ((runesize_t)offsetof(Type, ty_Info))
480
481 /*
482  * Weak aliases to the actual type label for well-defined type names
483  */
484 struct TypeRegNode;
485
486 typedef RUNE_HEAD(typereglist, TypeRegNode) typereglist_t;
487
488 typedef struct TypeRegNode {
489         RUNE_ENTRY(TypeRegNode) tr_Node;
490         string_t        tr_Id;
491         const char      *tr_LinkName;
492         Type            *tr_Type;
493 } TypeRegNode;
494
495 #define ty_ClassType    u.ClassType
496 #define ty_ImportType   u.ImportType
497 #define ty_PtrType      u.PtrType
498 #define ty_CPtrType     u.PtrType
499 #define ty_AryType      u.AryType
500 #define ty_CompType     u.CompType
501 #define ty_ArgsType     u.CompType
502 #define ty_VarType      u.VarType
503 #define ty_ProcType     u.ProcType
504 #define ty_QualType     u.QualType
505 #define ty_StorType     u.StorType
506 #define ty_UnresType    u.UnresType
507 #define ty_RefType      u.PtrType       /* must be same as PtrType */
508
509 #define TY_CLASS        1       /* the type represents a base class */
510 #define TY_PTRTO        2       /* the type is a pointer to BLAH */
511 #define TY_ARYOF        3       /* the type is an array of BLAH */
512 #define TY_COMPOUND     4       /* the type is compound, made up of BLAH */
513 #define TY_PROC         5       /* the type is a procedure */
514 #define TY_IMPORT       6
515 #define TY_STORAGE      7       /* as a special raw-storage type */
516 #define TY_ARGS         8       /* procedure arguments (compound) type */
517 #define TY_VAR          9       /* variable procedure arguments */
518 #define TY_DYNAMIC      10      /* run-time type (must be cast) (note 1) */
519 #define TY_UNRESOLVED   11      /* unresolved identifier path */
520 #define TY_REFTO        12      /* reference type (no indrection) */
521 #define TY_CPTRTO       13      /* C pointer type (no PointerStor) */
522
523 #define TF_RESOLVING    0x000001    /* type fully resolved */
524 #define TF_RESOLVED     0x000002    /* type fully resolved */
525 #define TF_DEFINED      0x000004    /* type has been defined, else only refd */
526 #define TF_NOINIT       0x000008    /* (interpreter - status) */
527 #define TF_HASLVPTR     0x000010    /* is or contains arg-lvalue, or ptr */
528 #define TF_HASCONSTRUCT 0x000020    /* contains constructor */
529 #define TF_HASDESTRUCT  0x000040    /* contains destructor */
530 #define TF_TMPRESOLVED  0x000080    /* temporary storage for exp eval resolv */
531 #define TF_CONDESDATA   0x000100    /* constr/destruct data as well as procs */
532 #define TF_HASGCONSTRUCT 0x00200    /* contains global constructor */
533 #define TF_HASGDESTRUCT 0x000400    /* contains global destructor */
534 #define TF_ISUNSIGNED   0x000800    /* Unsigned Integer (helper) */
535 #define TF_ISFLOATING   0x001000    /* Floating Point   (helper) */
536 #define TF_ISINTEGER    0x002000    /* Unsigned or signed integer (helper) */
537 #define TF_HASASS       0x004000    /* has or contains assignments {*/
538 #define TF_ISBOOL       0x008000    /* Boolean (helper) */
539 #define TF_GENERATING   0x010000    /* backend generation */
540 #define TF_COLLAPSED    0x020000    /* collapse pass in prog or done */
541 #define TF_LAYOUT       0x040000    /* available for global layout */
542 #define TF_ISINTERNAL   0x080000    /* special internal type, do not collapse */
543 #define TF_ALIGNRESOLVED 0x100000   /* alignment resolved */
544
545 /*
546  * Special storage qualifier masks
547  */
548 #define SF_MASK_ARY_INHERIT     (SF_CONST|SF_VOLATILE|SF_LVALUE|SF_NOZERO)
549
550 /*
551  * Global Info structure
552  */
553 typedef struct GlobInfo {
554         char    *gi_Label;              /* location of global entity */
555         runesize_t gi_Offset;
556         runesize_t gi_Bytes;
557         Type    *gi_Type;
558         int     gi_Flags;
559         int     gi_Hash;
560         struct SemGroup *gi_RSSG;       /* SG for global RefStor */
561         struct GlobInfo *gi_HNext;
562 } GlobInfo;
563
564 #define GLF_GENERATING  0x00000001
565
566 /*
567  * Needed for inlines
568  */
569 Type *TypeToQualType(Type *otype, Type *ntype, int sqFlags, struct Exp *exp);
570
571 static __inline
572 Type *
573 AddTypeQual(Type *type, int sqFlags)
574 {
575         return(TypeToQualType(type, NULL, type->ty_SQFlags | sqFlags, NULL));
576 }
577
578 static __inline
579 Type *
580 DelTypeQual(Type *type, int sqFlags)
581 {
582         return(TypeToQualType(type, NULL, type->ty_SQFlags & ~sqFlags, NULL));
583 }
584
585 #define dassert_type(type, cond)        dassert(cond)
586
587 #endif