58b677b08d91e385d955209463d95c8f2130882e
[cacao.git] / typeinfo.h
1 /* typeinfo.h - type system used by the type checker
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Edwin Steiner
28
29    $Id: typeinfo.h 706 2003-12-07 17:28:29Z twisti $
30
31 */
32
33
34 #ifndef _TYPEINFO_H
35 #define _TYPEINFO_H
36
37 #include <stdio.h>
38 #include "global.h"
39
40 /* resolve typedef cycles *****************************************************/
41
42 typedef struct typeinfo typeinfo;
43 typedef struct typeinfo_mergedlist typeinfo_mergedlist;
44
45 /* global variables ***********************************************************/
46
47 /* XXX move this documentation to global.h */
48 /* The following classinfo pointers are used internally by the type system.
49  * Please do not use them directly, use the TYPEINFO_ macros instead.
50  */
51
52 /*
53  * pseudo_class_Arraystub
54  *     (extends Object implements Cloneable, java.io.Serializable)
55  *
56  *     If two arrays of incompatible component types are merged,
57  *     the resulting reference has no accessible components.
58  *     The result does, however, implement the interfaces Cloneable
59  *     and java.io.Serializable. This pseudo class is used internally
60  *     to represent such results. (They are *not* considered arrays!)
61  *
62  * pseudo_class_Null
63  *
64  *     This pseudo class is used internally to represent the
65  *     null type.
66  */
67
68 /* data structures for the type system ****************************************/
69
70 /* The typeinfo structure stores detailed information on reference types.
71  * (stack elements, variables, etc. with type == TYPE_ADR.)
72  * XXX: exclude ReturnAddresses?
73  *
74  * For primitive types either there is no typeinfo allocated or the
75  * typeclass pointer in the typeinfo struct is NULL.
76  *
77  * CAUTION: The typeinfo structure should be considered opaque outside of
78  *          typeinfo.[ch]. Please use the macros and functions defined here to
79  *          access typeinfo structures!
80  */
81
82 /* At all times *exactly one* of the following conditions is true for
83  * a particular typeinfo struct:
84  *
85  * A) typeclass == NULL
86  *
87  *        In this case the other fields of the structure
88  *        are INVALID.
89  *
90  * B) typeclass == pseudo_class_Null
91  *
92  *        XXX
93  *
94  * C) typeclass is an array class
95  *
96  *        XXX
97  *
98  * D) typeclass == pseudo_class_Arraystub
99  *
100  *        XXX
101  *
102  * E) typeclass is an interface
103  *
104  *        XXX
105  *
106  * F) typeclass is a (non-pseudo-)class != java.lang.Object
107  *
108  *        XXX
109  *        All classinfos in u.merged.list (if any) are
110  *        subclasses of typeclass.
111  *
112  * G) typeclass is java.lang.Object
113  *
114  *        XXX
115  *        In this case u.merged.count and u.merged.list
116  *        are valid and may be non-zero.
117  *        The classinfos in u.merged.list (if any) can be
118  *        classes, interfaces or pseudo classes.
119  */
120
121 /* The following algorithm is used to determine if the type described
122  * by this typeinfo struct supports the interface X:
123  *
124  *     1) If typeclass is X or a subinterface of X the answer is "yes".
125  *     2) If typeclass is a (pseudo) class implementing X the answer is "yes".
126  *     3) XXX If typeclass is not an array and u.merged.count>0
127  *        and all classes/interfaces in u.merged.list implement X
128  *        the answer is "yes".
129  *     4) If none of the above is true the answer is "no".
130  */
131
132 /*
133  * CAUTION: The typeinfo structure should be considered opaque outside of
134  *          typeinfo.[ch]. Please use the macros and functions defined here to
135  *          access typeinfo structures!
136  */
137 struct typeinfo {
138         classinfo           *typeclass;
139         classinfo           *elementclass; /* valid if dimension>0 */
140         typeinfo_mergedlist *merged;
141         u1                   dimension;
142         u1                   elementtype;  /* valid if dimension>0 */
143 };
144
145 struct typeinfo_mergedlist {
146         s4         count;
147         classinfo *list[1]; /* variable length! */
148 };
149
150 /****************************************************************************/
151 /* MACROS                                                                   */
152 /****************************************************************************/
153
154 /* XXX wrap macro blocks in do { } while(0) */
155
156 /* NOTE: These macros take typeinfo *structs* not pointers as arguments.
157  *       You have to dereference any pointers.
158  */
159
160 /* internally used macros ***************************************************/
161
162 /* internal, don't use this explicitly! */
163 #define TYPEINFO_ALLOCMERGED(mergedlist,count)                  \
164             {(mergedlist) = (typeinfo_mergedlist*)dump_alloc(   \
165                 sizeof(typeinfo_mergedlist)                     \
166                 + ((count)-1)*sizeof(classinfo*));}
167
168 /* internal, don't use this explicitly! */
169 #define TYPEINFO_FREEMERGED(mergedlist)
170
171 /* internal, don't use this explicitly! */
172 #define TYPEINFO_FREEMERGED_IF_ANY(mergedlist)
173
174 /* macros for type queries **************************************************/
175
176 #define TYPEINFO_IS_PRIMITIVE(info)                             \
177             ((info).typeclass == NULL)
178
179 #define TYPEINFO_IS_REFERENCE(info)                             \
180             ((info).typeclass != NULL)
181
182 #define TYPEINFO_IS_NULLTYPE(info)                              \
183             ((info).typeclass == pseudo_class_Null)
184
185 /* macros for array type queries ********************************************/
186
187 #define TYPEINFO_IS_ARRAY(info)                                 \
188             ( TYPEINFO_IS_REFERENCE(info)                       \
189               && ((info).dimension != 0) )
190
191 #define TYPEINFO_IS_SIMPLE_ARRAY(info)                          \
192             ( ((info).dimension == 1) )
193
194 #define TYPEINFO_IS_ARRAY_ARRAY(info)                           \
195             ( ((info).dimension >= 2) )
196
197 #define TYPEINFO_IS_PRIMITIVE_ARRAY(info,arraytype)             \
198             ( TYPEINFO_IS_SIMPLE_ARRAY(info)                    \
199               && ((info).elementtype == (arraytype)) )
200
201 #define TYPEINFO_IS_OBJECT_ARRAY(info)                          \
202             ( TYPEINFO_IS_SIMPLE_ARRAY(info)                    \
203               && ((info).elementclass != NULL) )
204
205 /* assumes that info describes an array type */
206 #define TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info)                 \
207             ( ((info).elementclass != NULL)                     \
208               || ((info).dimension >= 2) )
209
210 #define TYPEINFO_IS_ARRAY_OF_REFS(info)                         \
211             ( TYPEINFO_IS_ARRAY(info)                           \
212               && TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info) )
213
214 /* queries allowing null types **********************************************/
215
216 #define TYPEINFO_MAYBE_ARRAY(info)                              \
217     (TYPEINFO_IS_ARRAY(info) || TYPEINFO_IS_NULLTYPE(info))
218
219 #define TYPEINFO_MAYBE_PRIMITIVE_ARRAY(info,at)                 \
220     (TYPEINFO_IS_PRIMITIVE_ARRAY(info,at) || TYPEINFO_IS_NULLTYPE(info))
221
222 #define TYPEINFO_MAYBE_ARRAY_OF_REFS(info)                      \
223     (TYPEINFO_IS_ARRAY_OF_REFS(info) || TYPEINFO_IS_NULLTYPE(info))
224
225
226 /* macros for initializing typeinfo structures ******************************/
227
228 #define TYPEINFO_INIT_PRIMITIVE(info)                           \
229             {(info).typeclass = NULL;                           \
230              (info).elementclass = NULL;                        \
231              (info).merged = NULL;                              \
232              (info).dimension = 0;                              \
233              (info).elementtype = 0;}
234
235 #define TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,cinfo)   \
236             {(info).typeclass = (cinfo);                \
237              (info).elementclass = NULL;                \
238              (info).merged = NULL;                      \
239              (info).dimension = 0;                      \
240              (info).elementtype = 0;}
241
242 #define TYPEINFO_INIT_NULLTYPE(info)                            \
243             TYPEINFO_INIT_CLASSINFO(info,pseudo_class_Null)
244
245 #define TYPEINFO_INIT_PRIMITIVE_ARRAY(info,arraytype)                   \
246     TYPEINFO_INIT_CLASSINFO(info,primitivetype_table[arraytype].arrayclass);
247
248 #define TYPEINFO_INIT_CLASSINFO(info,cls)                               \
249         {if (((info).typeclass = (cls))->vftbl->arraydesc) {              \
250                 if ((cls)->vftbl->arraydesc->elementvftbl)                \
251                     (info).elementclass = (cls)->vftbl->arraydesc->elementvftbl->class; \
252                 else                                                    \
253                     (info).elementclass = NULL;                         \
254                 (info).dimension = (cls)->vftbl->arraydesc->dimension;    \
255                 (info).elementtype = (cls)->vftbl->arraydesc->elementtype;\
256             }                                                           \
257             else {                                                      \
258                 (info).elementclass = NULL;                             \
259                 (info).dimension = 0;                                   \
260                 (info).elementtype = 0;                                 \
261             }                                                           \
262             (info).merged = NULL;}
263
264 #define TYPEINFO_INIT_FROM_FIELDINFO(info,fi)                   \
265             typeinfo_init_from_descriptor(&(info),              \
266                 (fi)->descriptor->text,utf_end((fi)->descriptor));
267
268 /* macros for freeing typeinfo structures ***********************************/
269
270 #define TYPEINFO_FREE(info)                                     \
271             {TYPEINFO_FREEMERGED_IF_ANY((info).merged);         \
272              (info).merged = NULL;}
273
274 /* macros for writing types (destination must have been initialized) ********/
275 /* XXX delete them? */
276
277 #define TYPEINFO_PUT_NULLTYPE(info)                             \
278             {(info).typeclass = pseudo_class_Null;}
279
280 #define TYPEINFO_PUT_NON_ARRAY_CLASSINFO(info,cinfo)            \
281             {(info).typeclass = (cinfo);}
282
283 #define TYPEINFO_PUT_CLASSINFO(info,cls)                                \
284         {if (((info).typeclass = (cls))->vftbl->arraydesc) {              \
285                 if ((cls)->vftbl->arraydesc->elementvftbl)                \
286                     (info).elementclass = (cls)->vftbl->arraydesc->elementvftbl->class; \
287                 (info).dimension = (cls)->vftbl->arraydesc->dimension;    \
288                 (info).elementtype = (cls)->vftbl->arraydesc->elementtype; \
289             }}
290
291 /* srcarray must be an array (not checked) */
292 #define TYPEINFO_PUT_COMPONENT(srcarray,dst)                    \
293             {typeinfo_put_component(&(srcarray),&(dst));}
294
295 /* macros for copying types (destinition is not checked or freed) ***********/
296
297 /* TYPEINFO_COPY makes a shallow copy, the merged pointer is simply copied. */
298 #define TYPEINFO_COPY(src,dst)                                  \
299             {(dst) = (src);}
300
301 /* TYPEINFO_CLONE makes a deep copy, the merged list (if any) is duplicated
302  * into a newly allocated array.
303  */
304 #define TYPEINFO_CLONE(src,dst)                                 \
305             {(dst) = (src);                                     \
306              if ((dst).merged) typeinfo_clone(&(src),&(dst));}
307
308 /****************************************************************************/
309 /* FUNCTIONS                                                                */
310 /****************************************************************************/
311
312 /* inquiry functions (read-only) ********************************************/
313
314 bool typeinfo_is_array(typeinfo *info);
315 bool typeinfo_is_primitive_array(typeinfo *info,int arraytype);
316 bool typeinfo_is_array_of_refs(typeinfo *info);
317
318 bool typeinfo_implements_interface(typeinfo *info,classinfo *interf);
319 bool typeinfo_is_assignable(typeinfo *value,typeinfo *dest);
320
321 /* initialization functions *************************************************/
322
323 void typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr);
324 void typeinfo_init_component(typeinfo *srcarray,typeinfo *dst);
325
326 int  typeinfo_count_method_args(utf *d,bool twoword); /* this not included */
327 void typeinfo_init_from_method_args(utf *desc,u1 *typebuf,
328                                     typeinfo *infobuf,
329                                     int buflen,bool twoword,
330                                     int *returntype,typeinfo *returntypeinfo);
331
332 void typeinfo_clone(typeinfo *src,typeinfo *dest);
333
334 /* functions for the type system ********************************************/
335
336 void typeinfo_free(typeinfo *info);
337
338 bool typeinfo_merge(typeinfo *dest,typeinfo* y);
339
340 /* debugging helpers ********************************************************/
341
342 #ifdef TYPEINFO_DEBUG
343
344 void typeinfo_test();
345 void typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc);
346 void typeinfo_print(FILE *file,typeinfo *info,int indent);
347 void typeinfo_print_short(FILE *file,typeinfo *info);
348 void typeinfo_print_type(FILE *file,int type,typeinfo *info);
349
350 #endif // TYPEINFO_DEBUG
351
352 #endif /* _TYPEINFO_H */
353
354
355 /*
356  * These are local overrides for various environment variables in Emacs.
357  * Please do not remove this and leave it at the end of the file, where
358  * Emacs will automagically detect them.
359  * ---------------------------------------------------------------------
360  * Local variables:
361  * mode: c
362  * indent-tabs-mode: t
363  * c-basic-offset: 4
364  * tab-width: 4
365  * End:
366  */