* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / jit / verify / typeinfo.h
1 /* typeinfo.h - type system used by the type checker
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Edwin Steiner
28
29    $Id: typeinfo.h 4357 2006-01-22 23:33:38Z twisti $
30
31 */
32
33 #ifndef _TYPEINFO_H
34 #define _TYPEINFO_H
35
36 #include "config.h"
37 #include "vm/types.h"
38
39 #include "vm/global.h"
40 #include "vm/references.h"
41
42
43 /* configuration **************************************************************/
44
45 /*
46  * TYPECHECK_STATISTICS activates gathering statistical information.
47  * TYPEINFO_DEBUG activates debug checks and debug helpers in typeinfo.c
48  * TYPECHECK_DEBUG activates debug checks in typecheck.c
49  * TYPEINFO_DEBUG_TEST activates the typeinfo test at startup.
50  * TYPECHECK_VERBOSE_IMPORTANT activates important debug messages
51  * TYPECHECK_VERBOSE activates all debug messages
52  * TYPEINFO_VERBOSE activates debug prints in typeinfo.c
53  */
54 #ifdef ENABLE_VERIFIER
55 #ifndef NDEBUG
56 /*#define TYPECHECK_STATISTICS*/
57 #define TYPEINFO_DEBUG
58 /*#define TYPEINFO_VERBOSE*/
59 #define TYPECHECK_DEBUG
60 /*#define TYPEINFO_DEBUG_TEST*/
61 /*#define TYPECHECK_VERBOSE*/
62 /*#define TYPECHECK_VERBOSE_IMPORTANT*/
63 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
64 #define TYPECHECK_VERBOSE_OPT
65 #endif
66 #endif
67 #endif
68
69 #ifdef TYPECHECK_VERBOSE_OPT
70 extern bool typecheckverbose;
71 #endif
72
73 /* resolve typedef cycles *****************************************************/
74
75 typedef struct typeinfo typeinfo;
76 typedef struct typeinfo_mergedlist typeinfo_mergedlist;
77 typedef struct typedescriptor typedescriptor;
78 typedef struct typevector typevector;
79 typedef struct typeinfo_retaddr_set typeinfo_retaddr_set;
80
81 /* types **********************************************************************/
82
83 /* typecheck_result - return type for boolean and tristate  functions     */
84 /*                    which may also throw exceptions (typecheck_FAIL).   */
85
86 /* NOTE: Use the enum values, not the uppercase #define macros!          */
87 #define TYPECHECK_MAYBE  0x02
88 #define TYPECHECK_FAIL   0x04
89
90 typedef enum {
91         typecheck_FALSE = false,
92         typecheck_TRUE  = true,
93         typecheck_MAYBE = TYPECHECK_MAYBE,
94         typecheck_FAIL  = TYPECHECK_FAIL
95 } typecheck_result;
96
97 /* check that typecheck_MAYBE is not ambiguous */
98 #if TYPECHECK_MAYBE == true
99 #error "`typecheck_MAYBE` must not be the same as `true`"
100 #endif
101 #if TYPECHECK_MAYBE == false
102 #error "`typecheck_MAYBE` must not be the same as `false`"
103 #endif
104
105 /* check that typecheck_FAIL is not ambiguous */
106 #if (true & TYPECHECK_FAIL) != 0
107 #error "`true` must not have bit 0x02 set (conflicts with typecheck_FAIL)"
108 #endif
109
110 /* data structures for the type system ****************************************/
111
112 /* The typeinfo structure stores detailed information on address types.
113  * (stack elements, variables, etc. with type == TYPE_ADR.)
114  *
115  * There are two kinds of address types which can be distinguished by
116  * the value of the typeclass field:
117  *
118  * 1) typeclass == NULL: returnAddress type
119  *                       use TYPEINFO_IS_PRIMITIVE to test for this
120  *
121  * 2) typeclass != NULL: reference type
122  *                       use TYPEINFO_IS_REFERENCE to test for this
123  *
124  * Note: For non-address types either there is no typeinfo allocated
125  * or the fields of the typeinfo struct contain undefined values!
126  * DO NOT access the typeinfo for non-address types!
127  *
128  * CAUTION: The typeinfo structure should be considered opaque outside of
129  *          typeinfo.[ch]. Please use the macros and functions defined here to
130  *          access typeinfo structures!
131  */
132
133 /* At all times *exactly one* of the following conditions is true for
134  * a particular typeinfo struct:
135  *
136  * A) typeclass == NULL
137  *
138  *        This is a returnAddress type. The interpretation of the
139  *        elementclass field depends on wether this typeinfo describes
140  *        a stack slot or a local variable:
141  *
142  *        stack slot: elementclass is a pointer to a
143  *            typeinfo_retaddr_set which contains a return target for
144  *            every vector in the current set of local variable vectors.
145  *            See typeinfo_retaddr_set and typevector below.
146  *
147  *        local variable: elementclass is the return target (when cast
148  *            to basicblock *)
149  *
150  *        Use TYPEINFO_IS_PRIMITIVE to check for this.
151  *        Use TYPEINFO_RETURNADDRESS to access the pointer in elementclass.
152  *        Don't access other fields of the struct.
153  *
154  * B) typeclass == pseudo_class_Null
155  *
156  *        This is the null-reference type. 
157  *        Use TYPEINFO_IS_NULLTYPE to check for this.
158  *        Don't access other fields of the struct.
159  *
160  * C) typeclass == pseudo_class_New
161  *
162  *        This is an 'uninitialized object' type. elementclass can be
163  *        cast to instruction* and points to the NEW instruction
164  *        responsible for creating this type.
165  *
166  *        Use TYPEINFO_NEWOBJECT_INSTRUCTION to access the pointer in
167  *        elementclass.
168  *        Don't access other fields of the struct.
169  *
170  * D) typeclass == pseudo_class_Arraystub
171  *
172  *        This type is used to represent the result of merging array types
173  *        with incompatible component types. An arraystub allows no access
174  *        to its components (since their type is undefined), but it allows
175  *        operations which act directly on an arbitrary array type (such as
176  *        requesting the array size).
177  *
178  *        NOTE: An array stub does *not* count as an array. It has dimension
179  *              zero.
180  *
181  *        Otherwise like a normal class reference type.
182  *        Don't access other fields of the struct.
183  *
184  * E) typeclass is an array class
185  *
186  *        An array reference.
187  *            elementclass...typeclass of the element type
188  *            dimension......dimension of the array (>=1)
189  *            elementtype....element type (ARRAYTYPE_...)
190  *            merged.........mergedlist of the element type
191  *
192  *        Use TYPEINFO_IS_ARRAY to check for this case.
193  *
194  *        The elementclass may be one of the following:
195  *        1) pseudo_class_Arraystub
196  *        2) an unresolved type
197  *        3) a loaded interface
198  *        4) a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
199  *                Note: `merged` may be used
200  *        5) (BOOTSTRAP)java.lang.Object
201  *                Note: `merged` may be used
202  *
203  *        For the semantics of the merged field in cases 4) and 5) consult the 
204  *        corresponding descriptions with `elementclass` replaced by `typeclass`.
205  *
206  * F) typeclass is an unresolved type (a symbolic class/interface reference)
207  *
208  *        The type has not been resolved yet. (Meaning it corresponds to an
209  *        unloaded class or interface).
210  *        Don't access other fields of the struct.
211  *
212  * G) typeclass is a loaded interface
213  *
214  *        An interface reference type.
215  *        Don't access other fields of the struct.
216  *
217  * H) typeclass is a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
218  *
219  *        A loaded class type.
220  *        All classref_or_classinfos in u.merged.list (if any) are
221  *        loaded subclasses of typeclass (no interfaces, array classes, or
222  *        unresolved types).
223  *        Don't access other fields of the struct.
224  *
225  * I) typeclass is (BOOTSTRAP)java.lang.Object
226  *
227  *        The most general kind of reference type.
228  *        In this case u.merged.count and u.merged.list
229  *        are valid and may be non-zero.
230  *        The classref_or_classinfos in u.merged.list (if any) may be
231  *        classes, interfaces, pseudo classes or unresolved types.
232  *        Don't access other fields of the struct.
233  */
234
235 /* The following algorithm is used to determine if the type described
236  * by this typeinfo struct supports the interface X:  * XXX add MAYBE *
237  *
238  *     1) If typeclass is X or a subinterface of X the answer is "yes".
239  *     2) If typeclass is a (pseudo) class implementing X the answer is "yes".
240  *     3) If typeclass is not an array and u.merged.count>0
241  *        and all classes/interfaces in u.merged.list implement X
242  *        the answer is "yes".
243  *     4) If none of the above is true the answer is "no".
244  */
245
246 /*
247  * CAUTION: The typeinfo structure should be considered opaque outside of
248  *          typeinfo.[ch]. Please use the macros and functions defined here to
249  *          access typeinfo structures!
250  */
251 struct typeinfo {
252         classref_or_classinfo  typeclass;
253         classref_or_classinfo  elementclass; /* valid if dimension>0 */ /* various uses! */
254         typeinfo_mergedlist   *merged;
255         u1                     dimension;
256         u1                     elementtype;  /* valid if dimension>0           */
257 };
258
259 struct typeinfo_mergedlist {
260         s4                    count;
261         classref_or_classinfo list[1];       /* variable length!                        */
262 };
263
264 /*-----------------------------------------------------------------------*/
265 /* a typeinfo_retaddr_set stores the set of possible returnAddresses     */
266 /* that may be in a particular stack slot at a particular point in the   */
267 /* program.                                                              */
268 /*                                                                       */
269 /* There may be one or more alternative returnAddresses if the           */
270 /* instruction can be reached via one or more JSR jumps (among other     */
271 /* control-flow paths                                                    */
272 /*-----------------------------------------------------------------------*/
273
274 struct typeinfo_retaddr_set {
275         typeinfo_retaddr_set *alt;  /* next alternative in set               */
276         void                 *addr; /* return address                        */
277 };
278
279 /* a type descriptor stores a basic type and the typeinfo                */
280 /* this is used for storing the type of a local variable, and for        */
281 /* storing types in the signature of a method                            */
282
283 struct typedescriptor {
284         typeinfo        info;     /* valid if type == TYPE_ADR               */
285         u1              type;     /* basic type (TYPE_INT, ...)              */
286 };
287
288 /*-----------------------------------------------------------------------*/
289 /* typevectors are used to store the types of all local variables        */
290 /* at a given point in the program.                                      */
291 /*                                                                       */
292 /* There may be more than one possible typevector for the local          */
293 /* variables at a given instruction if the instruction can be reached    */
294 /* via one or more JSR jumps (among other control-flow paths).           */
295 /*                                                                       */
296 /* This is called the set of alternative type vectors at that            */
297 /* particular point in the program.                                      */
298 /*-----------------------------------------------------------------------*/
299
300 struct typevector {
301         typevector      *alt;     /* next alternative in typevector set      */
302         int              k;       /* for lining up with the stack set        */
303         typedescriptor   td[1];   /* types of locals, variable length!       */
304 };
305
306 /****************************************************************************/
307 /* MACROS                                                                   */
308 /****************************************************************************/
309
310 /* NOTE: The TYPEINFO macros take typeinfo *structs*, not pointers as
311  *       arguments.  You have to dereference any pointers.
312  */
313
314 /* typevectors **************************************************************/
315
316 #define TYPEVECTOR_SIZE(size)                                           \
317     ((sizeof(typevector) - sizeof(typedescriptor))      \
318      + (size)*sizeof(typedescriptor))
319
320 #define DNEW_TYPEVECTOR(size)                                           \
321     ((typevector*)dump_alloc(TYPEVECTOR_SIZE(size)))
322
323 #define DMNEW_TYPEVECTOR(num,size)                                              \
324     ((void*)dump_alloc((num) * TYPEVECTOR_SIZE(size)))
325
326 #define MGET_TYPEVECTOR(array,index,size) \
327     ((typevector*) (((u1*)(array)) + TYPEVECTOR_SIZE(size) * (index)))
328
329 /* internally used macros ***************************************************/
330
331 /* internal, don't use this explicitly! */
332 #define TYPEINFO_ALLOCMERGED(mergedlist,count)                  \
333     do {(mergedlist) = (typeinfo_mergedlist*)dump_alloc(        \
334             sizeof(typeinfo_mergedlist)                         \
335             + ((count)-1)*sizeof(classinfo*));} while(0)
336
337 /* internal, don't use this explicitly! */
338 #define TYPEINFO_FREEMERGED(mergedlist)
339
340 /* internal, don't use this explicitly! */
341 #define TYPEINFO_FREEMERGED_IF_ANY(mergedlist)
342
343 /* macros for type queries **************************************************/
344
345 #define TYPEINFO_IS_PRIMITIVE(info)                             \
346             ((info).typeclass.any == NULL)
347
348 #define TYPEINFO_IS_REFERENCE(info)                             \
349             ((info).typeclass.any != NULL)
350
351 #define TYPEINFO_IS_NULLTYPE(info)                              \
352             ((info).typeclass.cls == pseudo_class_Null)
353
354 #define TYPEINFO_IS_NEWOBJECT(info)                             \
355             ((info).typeclass.cls == pseudo_class_New)
356
357 #define TYPEINFO_IS_JAVA_LANG_CLASS(info)                       \
358             ((info).typeclass.cls == class_java_lang_Class)
359
360 /* only use this if TYPEINFO_IS_PRIMITIVE returned true! */
361 #define TYPEINFO_RETURNADDRESS(info)                            \
362             ((info).elementclass.any)
363
364 /* only use this if TYPEINFO_IS_NEWOBJECT returned true! */
365 #define TYPEINFO_NEWOBJECT_INSTRUCTION(info)                    \
366                 ((info).elementclass.any)
367
368 /* only use this if TYPEINFO_IS_JAVA_LANG_CLASS returned true! */
369 #define TYPEINFO_JAVA_LANG_CLASS_CLASSREF(info)                 \
370                 ((info).elementclass.ref)
371
372 /* macros for array type queries ********************************************/
373
374 #define TYPEINFO_IS_ARRAY(info)                                 \
375             ( TYPEINFO_IS_REFERENCE(info)                       \
376               && ((info).dimension != 0) )
377
378 #define TYPEINFO_IS_SIMPLE_ARRAY(info)                          \
379             ( ((info).dimension == 1) )
380
381 #define TYPEINFO_IS_ARRAY_ARRAY(info)                           \
382             ( ((info).dimension >= 2) )
383
384 #define TYPEINFO_IS_PRIMITIVE_ARRAY(info,arraytype)             \
385             ( TYPEINFO_IS_SIMPLE_ARRAY(info)                    \
386               && ((info).elementtype == (arraytype)) )
387
388 #define TYPEINFO_IS_OBJECT_ARRAY(info)                          \
389             ( TYPEINFO_IS_SIMPLE_ARRAY(info)                    \
390               && ((info).elementclass.any != NULL) )
391
392 /* assumes that info describes an array type */
393 #define TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info)                 \
394             ( ((info).elementclass.any != NULL)                 \
395               || ((info).dimension >= 2) )
396
397 #define TYPEINFO_IS_ARRAY_OF_REFS(info)                         \
398             ( TYPEINFO_IS_ARRAY(info)                           \
399               && TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info) )
400
401 #define TYPE_IS_RETURNADDRESS(type,info)                        \
402             ( ((type)==TYPE_ADDRESS)                            \
403               && TYPEINFO_IS_PRIMITIVE(info) )
404
405 #define TYPE_IS_REFERENCE(type,info)                            \
406             ( ((type)==TYPE_ADDRESS)                            \
407               && !TYPEINFO_IS_PRIMITIVE(info) )
408
409 #define TYPEDESC_IS_RETURNADDRESS(td)                           \
410             TYPE_IS_RETURNADDRESS((td).type,(td).info)
411
412 #define TYPEDESC_IS_REFERENCE(td)                               \
413             TYPE_IS_REFERENCE((td).type,(td).info)
414
415 /* queries allowing the null type ********************************************/
416
417 #define TYPEINFO_MAYBE_ARRAY(info)                              \
418     (TYPEINFO_IS_ARRAY(info) || TYPEINFO_IS_NULLTYPE(info))
419
420 #define TYPEINFO_MAYBE_PRIMITIVE_ARRAY(info,at)                 \
421     (TYPEINFO_IS_PRIMITIVE_ARRAY(info,at) || TYPEINFO_IS_NULLTYPE(info))
422
423 #define TYPEINFO_MAYBE_ARRAY_OF_REFS(info)                      \
424     (TYPEINFO_IS_ARRAY_OF_REFS(info) || TYPEINFO_IS_NULLTYPE(info))
425
426 /* macros for initializing typeinfo structures ******************************/
427
428 #define TYPEINFO_INIT_PRIMITIVE(info)                           \
429          do {(info).typeclass.any = NULL;                       \
430              (info).elementclass.any = NULL;                    \
431              (info).merged = NULL;                              \
432              (info).dimension = 0;                              \
433              (info).elementtype = 0;} while(0)
434
435 #define TYPEINFO_INIT_RETURNADDRESS(info,adr)                   \
436          do {(info).typeclass.any = NULL;                       \
437              (info).elementclass.any = (adr);                   \
438              (info).merged = NULL;                              \
439              (info).dimension = 0;                              \
440              (info).elementtype = 0;} while(0)
441
442 #define TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,cinfo)   \
443          do {(info).typeclass.cls = (cinfo);            \
444              (info).elementclass.any = NULL;            \
445              (info).merged = NULL;                      \
446              (info).dimension = 0;                      \
447              (info).elementtype = 0;} while(0)
448
449 #define TYPEINFO_INIT_JAVA_LANG_CLASS(info,cr)                  \
450          do {(info).typeclass.any = class_java_lang_Class;      \
451              (info).elementclass.ref = (cr);                    \
452              (info).merged = NULL;                              \
453              (info).dimension = 0;                              \
454              (info).elementtype = 0;} while(0)
455
456 #define TYPEINFO_INIT_NULLTYPE(info)                            \
457             TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,pseudo_class_Null)
458
459 #define TYPEINFO_INIT_NEWOBJECT(info,instr)             \
460          do {(info).typeclass.cls = pseudo_class_New;   \
461              (info).elementclass.any = (instr);         \
462              (info).merged = NULL;                      \
463              (info).dimension = 0;                      \
464              (info).elementtype = 0;} while(0)
465
466 #define TYPEINFO_INIT_PRIMITIVE_ARRAY(info,arraytype)                   \
467     typeinfo_init_classinfo(&(info),primitivetype_table[arraytype].arrayclass);
468
469 /* macros for copying types (destinition is not checked or freed) ***********/
470
471 /* TYPEINFO_COPY makes a shallow copy, the merged pointer is simply copied. */
472 #define TYPEINFO_COPY(src,dst)                                  \
473     do {(dst) = (src);} while(0)
474
475 /* TYPEINFO_CLONE makes a deep copy, the merged list (if any) is duplicated
476  * into a newly allocated array.
477  */
478 #define TYPEINFO_CLONE(src,dst)                                 \
479     do {(dst) = (src);                                          \
480         if ((dst).merged) typeinfo_clone(&(src),&(dst));} while(0)
481
482 /****************************************************************************/
483 /* FUNCTIONS                                                                */
484 /****************************************************************************/
485
486 /* typevector functions *****************************************************/
487
488 /* element read-only access */
489 bool typevectorset_checktype(typevector *set,int index,int type);
490 bool typevectorset_checkreference(typevector *set,int index);
491 bool typevectorset_checkretaddr(typevector *set,int index);
492 int typevectorset_copymergedtype(methodinfo *m,typevector *set,int index,typeinfo *dst);
493 int typevectorset_mergedtype(methodinfo *m,typevector *set,int index,typeinfo *temp,typeinfo **result);
494
495 /* element write access */
496 void typevectorset_store(typevector *set,int index,int type,typeinfo *info);
497 void typevectorset_store_retaddr(typevector *set,int index,typeinfo *info);
498 void typevectorset_store_twoword(typevector *set,int index,int type);
499 bool typevectorset_init_object(typevector *set,void *ins,classref_or_classinfo initclass,int size);
500
501 /* vector functions */
502 bool typevector_separable_from(typevector *a,typevector *b,int size);
503 typecheck_result typevector_merge(methodinfo *m,typevector *dst,typevector *y,int size);
504
505 /* vector set functions */
506 typevector *typevectorset_copy(typevector *src,int k,int size);
507 void typevectorset_copy_inplace(typevector *src,typevector *dst,int size);
508 bool typevectorset_separable_with(typevector *set,typevector *add,int size);
509 typecheck_result typevectorset_collapse(methodinfo *m,typevector *dst,int size);
510 void typevectorset_add(typevector *dst,typevector *v,int size);
511 typevector *typevectorset_select(typevector **set,int retindex,void *retaddr);
512
513 /* inquiry functions (read-only) ********************************************/
514
515 bool typeinfo_is_array(typeinfo *info);
516 bool typeinfo_is_primitive_array(typeinfo *info,int arraytype);
517 bool typeinfo_is_array_of_refs(typeinfo *info);
518
519 typecheck_result typeinfo_is_assignable(typeinfo *value,typeinfo *dest);
520 typecheck_result typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest);
521
522 /* initialization functions *************************************************/
523
524 /* RETURN VALUE (bool):
525  *     true.............ok,
526  *     false............an exception has been thrown.
527  *
528  * RETURN VALUE (int):
529  *     >= 0.............ok,
530  *     -1...............an exception has been thrown.
531  */
532 void typeinfo_init_classinfo(typeinfo *info,classinfo *c);
533 bool typeinfo_init_class(typeinfo *info,classref_or_classinfo c);
534 bool typeinfo_init_component(typeinfo *srcarray,typeinfo *dst);
535
536 bool typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info);
537 bool typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,
538                                    typeinfo *infobuf,
539                                    int buflen,bool twoword,
540                                    u1 *returntype,typeinfo *returntypeinfo);
541 bool  typedescriptor_init_from_typedesc(typedescriptor *td,
542                                                                             typedesc *desc);
543 int  typedescriptors_init_from_methoddesc(typedescriptor *td,
544                                                                                   methoddesc *desc,
545                                                                                   int buflen,bool twoword,int startindex,
546                                                                                   typedescriptor *returntype);
547
548 void typeinfo_clone(typeinfo *src,typeinfo *dest);
549
550 /* freeing memory ***********************************************************/
551
552 void typeinfo_free(typeinfo *info);
553
554 /* functions for merging types **********************************************/
555
556 typecheck_result typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y);
557
558 /* debugging helpers ********************************************************/
559
560 #ifdef TYPEINFO_DEBUG
561
562 #include <stdio.h>
563
564 void typeinfo_test();
565 void typeinfo_print_class(FILE *file,classref_or_classinfo c);
566 void typeinfo_print(FILE *file,typeinfo *info,int indent);
567 void typeinfo_print_short(FILE *file,typeinfo *info);
568 void typeinfo_print_type(FILE *file,int type,typeinfo *info);
569 void typeinfo_print_stacktype(FILE *file,int type,typeinfo *info);
570 void typedescriptor_print(FILE *file,typedescriptor *td);
571 void typevector_print(FILE *file,typevector *vec,int size);
572 void typevectorset_print(FILE *file,typevector *set,int size);
573
574 #endif /* TYPEINFO_DEBUG */
575
576 #endif /* _TYPEINFO_H */
577
578
579 /*
580  * These are local overrides for various environment variables in Emacs.
581  * Please do not remove this and leave it at the end of the file, where
582  * Emacs will automagically detect them.
583  * ---------------------------------------------------------------------
584  * Local variables:
585  * mode: c
586  * indent-tabs-mode: t
587  * c-basic-offset: 4
588  * tab-width: 4
589  * End:
590  */