Fixed --disable-threads compiling issues (missing header includes).
[cacao.git] / src / vm / resolve.c
1 /* src/vm/resolve.c - resolving classes/interfaces/fields/methods
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 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    Changes:
30
31    $Id: resolve.c 2194 2005-04-03 16:13:27Z twisti $
32
33 */
34
35
36 #include <assert.h>
37
38 #include "mm/memory.h"
39 #include "vm/resolve.h"
40 #include "vm/access.h"
41 #include "vm/classcache.h"
42 #include "vm/exceptions.h"
43 #include "vm/loader.h"
44 #include "vm/linker.h"
45 #include "vm/classcache.h"
46 #include "vm/descriptor.h"
47 #include "vm/jit/jit.h"
48 #include "vm/jit/verify/typeinfo.h"
49
50
51 /******************************************************************************/
52 /* DEBUG HELPERS                                                              */
53 /******************************************************************************/
54
55 /*#define RESOLVE_VERBOSE*/
56
57 #ifndef NDEBUG
58 #define RESOLVE_DEBUG
59 #endif
60
61 #ifdef RESOLVE_DEBUG
62 #define RESOLVE_ASSERT(cond)  assert(cond)
63 #else
64 #define RESOLVE_ASSERT(cond)
65 #endif
66
67 /******************************************************************************/
68 /* CLASS RESOLUTION                                                           */
69 /******************************************************************************/
70
71 /* resolve symbolic class reference -- see resolve.h */
72 bool
73 resolve_class(classinfo *referer,methodinfo *refmethod,
74                           utf *classname,
75                           resolve_mode_t mode,
76                           classinfo **result)
77 {
78         classinfo *cls = NULL;
79         char *utf_ptr;
80         int len;
81         
82         RESOLVE_ASSERT(result);
83         RESOLVE_ASSERT(referer);
84         RESOLVE_ASSERT(classname);
85         RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
86         
87         *result = NULL;
88
89 #ifdef RESOLVE_VERBOSE
90         fprintf(stderr,"resolve_class(");
91         utf_fprint(stderr,referer->name);
92         fprintf(stderr,",");
93         utf_fprint(stderr,classname);
94         fprintf(stderr,")\n");
95 #endif
96
97         /* lookup if this class has already been loaded */
98         cls = classcache_lookup(referer->classloader,classname);
99
100 #ifdef RESOLVE_VERBOSE
101         fprintf(stderr,"    lookup result: %p\n",(void*)cls);
102 #endif
103         
104         if (!cls) {
105                 /* resolve array types */
106                 if (classname->text[0] == '[') {
107                         utf_ptr = classname->text + 1;
108                         len = classname->blength - 1;
109                         /* classname is an array type name */
110                         switch (*utf_ptr) {
111                                 case 'L':
112                                         utf_ptr++;
113                                         len -= 2;
114                                         /* FALLTHROUGH */
115                                 case '[':
116                                         /* the component type is a reference type */
117                                         /* resolve the component type */
118                                         if (!resolve_class(referer,refmethod,
119                                                                            utf_new(utf_ptr,len),
120                                                                            mode,&cls))
121                                                 return false; /* exception */
122                                         if (!cls) {
123                                                 RESOLVE_ASSERT(mode == resolveLazy);
124                                                 return true; /* be lazy */
125                                         }
126                                         /* create the array class */
127                                         cls = class_array_of(cls);
128                         }
129                 }
130                 else {
131                         /* the class has not been loaded, yet */
132                         if (mode == resolveLazy)
133                                 return true; /* be lazy */
134                 }
135
136 #ifdef RESOLVE_VERBOSE
137                 fprintf(stderr,"    loading...\n");
138 #endif
139
140                 /* load the class */
141                 if (!cls) {
142                         if (!load_class_from_classloader(classname,referer->classloader,&cls))
143                                 return false; /* exception */
144                 }
145         }
146
147         /* the class is now loaded */
148         RESOLVE_ASSERT(cls);
149         RESOLVE_ASSERT(cls->loaded);
150
151 #ifdef RESOLVE_VERBOSE
152         fprintf(stderr,"    checking access rights...\n");
153 #endif
154         
155         /* check access rights of referer to refered class */
156         if (!is_accessible_class(referer,cls)) {
157                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
158                                 "class is not accessible XXX add message");
159                 return false; /* exception */
160         }
161
162         /* resolution succeeds */
163 #ifdef RESOLVE_VERBOSE
164         fprintf(stderr,"    success.\n");
165 #endif
166         *result = cls;
167         return true;
168 }
169
170 bool
171 resolve_classref(methodinfo *refmethod,
172                                  constant_classref *ref,
173                                  resolve_mode_t mode,
174                              bool link,
175                                  classinfo **result)
176 {
177         return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
178 }
179
180 bool
181 resolve_classref_or_classinfo(methodinfo *refmethod,
182                                                           classref_or_classinfo cls,
183                                                           resolve_mode_t mode,
184                                                           bool link,
185                                                           classinfo **result)
186 {
187         classinfo *c;
188         
189         RESOLVE_ASSERT(cls.any);
190         RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
191         RESOLVE_ASSERT(result);
192
193         *result = NULL;
194
195         if (IS_CLASSREF(cls)) {
196                 /* we must resolve this reference */
197                 if (!resolve_class(cls.ref->referer,refmethod,cls.ref->name,
198                                                    mode,&c))
199                         return false; /* exception */
200         }
201         else {
202                 /* cls has already been resolved */
203                 c = cls.cls;
204                 RESOLVE_ASSERT(c->loaded);
205         }
206         RESOLVE_ASSERT(c || (mode == resolveLazy));
207
208         if (!c)
209                 return true; /* be lazy */
210         
211         RESOLVE_ASSERT(c);
212         RESOLVE_ASSERT(c->loaded);
213
214         if (link) {
215                 if (!c->linked)
216                         if (!link_class(c))
217                                 return false; /* exception */
218                 RESOLVE_ASSERT(c->linked);
219         }
220
221         /* succeeded */
222         *result = c;
223         return true;
224 }
225
226 bool 
227 resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
228 {
229         classinfo *cls;
230         
231         RESOLVE_ASSERT(d);
232         RESOLVE_ASSERT(result);
233
234         *result = NULL;
235
236 #ifdef RESOLVE_VERBOSE
237         fprintf(stderr,"resolve_class_from_typedesc(");
238         descriptor_debug_print_typedesc(stderr,d);
239         fprintf(stderr,",%i)\n",link);
240 #endif
241
242         if (d->classref) {
243                 /* a reference type */
244                 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
245                                                                                    resolveEager,link,&cls))
246                         return false; /* exception */
247         }
248         else {
249                 /* a primitive type */
250                 cls = primitivetype_table[d->decltype].class_primitive;
251                 RESOLVE_ASSERT(cls->loaded);
252                 if (!cls->linked)
253                         if (!link_class(cls))
254                                 return false; /* exception */
255         }
256         RESOLVE_ASSERT(cls);
257         RESOLVE_ASSERT(cls->loaded);
258         RESOLVE_ASSERT(!link || cls->linked);
259
260 #ifdef RESOLVE_VERBOSE
261         fprintf(stderr,"    result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
262 #endif
263
264         *result = cls;
265         return true;
266 }
267
268 /******************************************************************************/
269 /* SUBTYPE SET CHECKS                                                         */
270 /******************************************************************************/
271
272 /* for documentation see resolve.h */
273 bool
274 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
275                                                           unresolved_subtype_set *ref,
276                                                           classref_or_classinfo typeref,
277                                                           bool reversed,
278                                                           resolve_mode_t mode,
279                                                           resolve_err_t error,
280                                                           bool *checked)
281 {
282         classref_or_classinfo *setp;
283         classinfo *result;
284         classinfo *type;
285         typeinfo resultti;
286         typeinfo typeti;
287
288         RESOLVE_ASSERT(referer);
289         RESOLVE_ASSERT(ref);
290         RESOLVE_ASSERT(typeref.any);
291         RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
292         RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
293
294 #ifdef RESOLVE_VERBOSE
295         fprintf(stderr,"resolve_and_check_subtype_set\n");
296         unresolved_subtype_set_debug_dump(ref,stderr);
297         if (IS_CLASSREF(typeref)) {
298                 fprintf(stderr,"    ref: ");utf_fprint(stderr,typeref.ref->name);
299         }
300         else {
301                 fprintf(stderr,"    cls: ");utf_fprint(stderr,typeref.cls->name);
302         }
303         fprintf(stderr,"\n");
304 #endif
305
306         setp = ref->subtyperefs;
307
308         /* an empty set of tests always succeeds */
309         if (!setp || !setp->any) {
310                 if (checked)
311                         *checked = true;
312                 return true;
313         }
314
315         if (checked)
316                 *checked = false;
317
318         /* first resolve the type if necessary */
319         if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
320                 return false; /* exception */
321         if (!type)
322                 return true; /* be lazy */
323
324         RESOLVE_ASSERT(type);
325         RESOLVE_ASSERT(type->loaded);
326         RESOLVE_ASSERT(type->linked);
327         TYPEINFO_INIT_CLASSINFO(typeti,type);
328
329         for (; setp->any; ++setp) {
330                 /* first resolve the set member if necessary */
331                 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
332                         return false; /* exception */
333                 if (!result)
334                         return true; /* be lazy */
335
336                 RESOLVE_ASSERT(result);
337                 RESOLVE_ASSERT(result->loaded);
338                 RESOLVE_ASSERT(result->linked);
339
340 #ifdef RESOLVE_VERBOSE
341                 fprintf(stderr,"performing subclass test:\n");
342                 fprintf(stderr,"    ");utf_fprint(stderr,result->name);fputc('\n',stderr);
343                 fprintf(stderr,"  must be a %s of\n",(reversed) ? "superclass" : "subclass");
344                 fprintf(stderr,"    ");utf_fprint(stderr,type->name);fputc('\n',stderr);
345 #endif
346
347                 /* now check the subtype relationship */
348                 TYPEINFO_INIT_CLASSINFO(resultti,result);
349                 if (reversed) {
350                         /* we must test against `true` because `MAYBE` is also != 0 */
351                         if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
352 #ifdef RESOLVE_VERBOSE
353                                 fprintf(stderr,"reversed subclass test failed\n");
354 #endif
355                                 goto throw_error;
356                         }
357                 }
358                 else {
359                         /* we must test against `true` because `MAYBE` is also != 0 */
360                         if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
361 #ifdef RESOLVE_VERBOSE
362                                 fprintf(stderr,"subclass test failed\n");
363 #endif
364                                 goto throw_error;
365                         }
366                 }
367         }
368         
369         /* check succeeds */
370         if (checked)
371                 *checked = true;
372         return true;
373
374 throw_error:
375         if (error == resolveIllegalAccessError)
376                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
377                                 "illegal access to protected member XXX add message");
378         else
379                 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
380                                 "subtype constraint violated XXX add message");
381         return false; /* exception */
382 }
383
384 /******************************************************************************/
385 /* FIELD RESOLUTION                                                           */
386 /******************************************************************************/
387
388 /* for documentation see resolve.h */
389 bool
390 resolve_field(unresolved_field *ref,
391                           resolve_mode_t mode,
392                           fieldinfo **result)
393 {
394         classinfo *referer;
395         classinfo *container;
396         classinfo *declarer;
397         constant_classref *fieldtyperef;
398         fieldinfo *fi;
399         bool checked;
400         
401         RESOLVE_ASSERT(ref);
402         RESOLVE_ASSERT(result);
403         RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
404
405         *result = NULL;
406
407 #ifdef RESOLVE_VERBOSE
408         unresolved_field_debug_dump(ref,stderr);
409 #endif
410
411         /* the class containing the reference */
412         referer = ref->fieldref->classref->referer;
413         RESOLVE_ASSERT(referer);
414
415         /* first we must resolve the class containg the field */
416         if (!resolve_class(referer,ref->referermethod,
417                                            ref->fieldref->classref->name,mode,&container))
418         {
419                 /* the class reference could not be resolved */
420                 return false; /* exception */
421         }
422         if (!container)
423                 return true; /* be lazy */
424
425         RESOLVE_ASSERT(container);
426         RESOLVE_ASSERT(container->loaded && container->linked);
427
428         /* now we must find the declaration of the field in `container`
429          * or one of its superclasses */
430
431 #ifdef RESOLVE_VERBOSE
432                 fprintf(stderr,"    resolving field in class...\n");
433 #endif
434
435         fi = class_resolvefield(container,
436                                                         ref->fieldref->name,ref->fieldref->descriptor,
437                                                         referer,true);
438         if (!fi)
439                 return false; /* exception */
440
441         /* { the field reference has been resolved } */
442         declarer = fi->class;
443         RESOLVE_ASSERT(declarer);
444         RESOLVE_ASSERT(declarer->loaded && declarer->linked);
445
446 #ifdef RESOLVE_VERBOSE
447                 fprintf(stderr,"    checking static...\n");
448 #endif
449
450         /* check static */
451         if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
452                 /* a static field is accessed via an instance, or vice versa */
453                 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
454                                 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
455                                                          : "instance field accessed without instance");
456                 return false; /* exception */
457         }
458
459         /* for non-static accesses we have to check the constraints on the instance type */
460         if ((ref->flags & RESOLVE_STATIC) == 0) {
461 #ifdef RESOLVE_VERBOSE
462                 fprintf(stderr,"    checking instance types...\n");
463 #endif
464
465                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
466                                                                                    &(ref->instancetypes),
467                                                                                    CLASSREF_OR_CLASSINFO(container),
468                                                                                    false,
469                                                                                    mode,
470                                                                                    resolveLinkageError,&checked))
471                 {
472                         return false; /* exception */
473                 }
474                 if (!checked)
475                         return true; /* be lazy */
476         }
477
478         fieldtyperef = ref->fieldref->parseddesc.fd->classref;
479
480         /* for PUT* instructions we have to check the constraints on the value type */
481         if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
482                 RESOLVE_ASSERT(fieldtyperef);
483                 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
484                         /* check subtype constraints */
485                         if (!resolve_and_check_subtype_set(referer,ref->referermethod,
486                                                                                            &(ref->valueconstraints),
487                                                                                            CLASSREF_OR_CLASSINFO(fieldtyperef),
488                                                                                            false,
489                                                                                            mode,
490                                                                                            resolveLinkageError,&checked))
491                         {
492                                 return false; /* exception */
493                         }
494                         if (!checked)
495                                 return true; /* be lazy */
496                 }
497         }
498                                                                            
499         /* check access rights */
500         if (!is_accessible_member(referer,declarer,fi->flags)) {
501                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
502                                 "field is not accessible XXX add message");
503                 return false; /* exception */
504         }
505
506         /* check protected access */
507         if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
508                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
509                                                                                    &(ref->instancetypes),
510                                                                                    CLASSREF_OR_CLASSINFO(referer),
511                                                                                    false,
512                                                                                    mode,
513                                                                                    resolveIllegalAccessError,&checked))
514                 {
515                         return false; /* exception */
516                 }
517                 if (!checked)
518                         return true; /* be lazy */
519         }
520
521         /* impose loading constraint on field type */
522         if (fi->type == TYPE_ADR) {
523                 RESOLVE_ASSERT(fieldtyperef);
524                 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
525                                                                            fieldtyperef->name))
526                         return false; /* exception */
527         }
528
529         /* succeed */
530         *result = fi;
531         return true;
532 }
533
534 /******************************************************************************/
535 /* METHOD RESOLUTION                                                          */
536 /******************************************************************************/
537
538 /* for documentation see resolve.h */
539 bool
540 resolve_method(unresolved_method *ref,
541                            resolve_mode_t mode,
542                            methodinfo **result)
543 {
544         classinfo *referer;
545         classinfo *container;
546         classinfo *declarer;
547         methodinfo *mi;
548         typedesc *paramtypes;
549         int instancecount;
550         int i;
551         bool checked;
552         
553         RESOLVE_ASSERT(ref);
554         RESOLVE_ASSERT(result);
555         RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
556
557 #ifdef RESOLVE_VERBOSE
558         unresolved_method_debug_dump(ref,stderr);
559 #endif
560
561         *result = NULL;
562
563         /* the class containing the reference */
564         referer = ref->methodref->classref->referer;
565         RESOLVE_ASSERT(referer);
566
567         /* first we must resolve the class containg the method */
568         if (!resolve_class(referer,ref->referermethod,
569                                            ref->methodref->classref->name,mode,&container))
570         {
571                 /* the class reference could not be resolved */
572                 return false; /* exception */
573         }
574         if (!container)
575                 return true; /* be lazy */
576
577         RESOLVE_ASSERT(container);
578
579         /* now we must find the declaration of the method in `container`
580          * or one of its superclasses */
581
582         if ((container->flags & ACC_INTERFACE) != 0) {
583                 mi = class_resolveinterfacemethod(container,
584                                                                               ref->methodref->name,ref->methodref->descriptor,
585                                                                               referer,true);
586         }
587         else {
588                 mi = class_resolveclassmethod(container,
589                                                                           ref->methodref->name,ref->methodref->descriptor,
590                                                                           referer,true);
591         }
592         if (!mi)
593                 return false; /* exception */ /* XXX set exceptionptr? */
594
595         /* { the method reference has been resolved } */
596         declarer = mi->class;
597         RESOLVE_ASSERT(declarer);
598
599         /* check static */
600         if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
601                 /* a static method is accessed via an instance, or vice versa */
602                 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
603                                 (mi->flags & ACC_STATIC) ? "static method called via instance"
604                                                          : "instance method called without instance");
605                 return false; /* exception */
606         }
607
608         /* for non-static methods we have to check the constraints on the instance type */
609         if ((ref->flags & RESOLVE_STATIC) == 0) {
610                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
611                                                                                    &(ref->instancetypes),
612                                                                                    CLASSREF_OR_CLASSINFO(container),
613                                                                                    false,
614                                                                                    mode,
615                                                                                    resolveLinkageError,&checked))
616                 {
617                         return false; /* exception */
618                 }
619                 if (!checked)
620                         return true; /* be lazy */
621                 instancecount = 1;
622         }
623         else {
624                 instancecount = 0;
625         }
626
627         /* check subtype constraints for TYPE_ADR parameters */
628         RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
629         paramtypes = ref->methodref->parseddesc.md->paramtypes;
630         
631         for (i=0; i<(mi->paramcount-instancecount); ++i) {
632                 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
633                         RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
634                         if (ref->paramconstraints) {
635                                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
636                                                         ref->paramconstraints + i,
637                                                         CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
638                                                         false,
639                                                         mode,
640                                                         resolveLinkageError,&checked))
641                                 {
642                                         return false; /* exception */
643                                 }
644                                 if (!checked)
645                                         return true; /* be lazy */
646                         }
647                 }
648         }
649
650         /* check access rights */
651         if (!is_accessible_member(referer,declarer,mi->flags)) {
652                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
653                                 "method is not accessible XXX add message");
654                 return false; /* exception */
655         }
656
657         /* check protected access */
658         if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
659                 /* XXX do we also need to check (referer subclass_of declarer)? */
660                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
661                                                                                    &(ref->instancetypes),
662                                                                                    CLASSREF_OR_CLASSINFO(referer),
663                                                                                    false,
664                                                                                    mode,
665                                                                                    resolveIllegalAccessError,&checked))
666                 {
667                         return false; /* exception */
668                 }
669                 if (!checked)
670                         return true; /* be lazy */
671         }
672
673         /* impose loading constraints on parameters (including instance) */
674         paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
675         for (i=0; i<mi->paramcount; ++i) {
676                 if (mi->paramtypes[i] == TYPE_ADR) {
677                         utf *name;
678                         
679                         if (i < instancecount)
680                                 name = container->name; /* XXX should this be declarer->name? */
681                         else
682                                 name = paramtypes[i].classref->name;
683                         
684                         if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
685                                 return false; /* exception */
686                 }
687         }
688
689         /* impose loading constraing onto return type */
690         if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
691                 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
692                                 ref->methodref->parseddesc.md->returntype.classref->name))
693                         return false; /* exception */
694         }
695
696         /* succeed */
697         *result = mi;
698         return true;
699 }
700
701 /******************************************************************************/
702 /* CREATING THE DATA STRUCTURES                                               */
703 /******************************************************************************/
704
705 static bool
706 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
707                 unresolved_subtype_set *stset,typeinfo *tinfo,
708                 constant_classref *declaredtype)
709 {
710         int count;
711         int i;
712         
713         RESOLVE_ASSERT(stset);
714         RESOLVE_ASSERT(tinfo);
715
716 #ifdef RESOLVE_VERBOSE
717         fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
718 #ifdef TYPEINFO_DEBUG
719         typeinfo_print(stderr,tinfo,4);
720         fprintf(stderr,"\n");
721 #endif
722         fprintf(stderr,"    declared type:");utf_fprint(stderr,declaredtype->name);
723         fprintf(stderr,"\n");
724 #endif
725
726         if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
727                 *exceptionptr = new_verifyerror(refmethod,
728                                 "Invalid use of returnAddress");
729                 return false;
730         }
731
732         if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
733                 *exceptionptr = new_verifyerror(refmethod,
734                                 "Invalid use of uninitialized object");
735                 return false;
736         }
737
738         /* the nulltype is always assignable (XXX for reversed?) */
739         if (TYPEINFO_IS_NULLTYPE(*tinfo))
740                 goto empty_set;
741
742         /* every type is assignable to (BOOTSTRAP)java.lang.Object */
743         if (declaredtype->name == utf_java_lang_Object
744                         && referer->classloader == NULL)
745         {
746                 goto empty_set;
747         }
748
749         if (tinfo->merged) {
750                 count = tinfo->merged->count;
751                 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
752                 for (i=0; i<count; ++i) {
753                         stset->subtyperefs[i] = tinfo->merged->list[i];
754                 }
755                 stset->subtyperefs[count].any = NULL; /* terminate */
756         }
757         else {
758                 if ((IS_CLASSREF(tinfo->typeclass)
759                                         ? tinfo->typeclass.ref->name 
760                                         : tinfo->typeclass.cls->name) == declaredtype->name)
761                 {
762                         goto empty_set;
763                 }
764                 else {
765                         stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
766                         stset->subtyperefs[0] = tinfo->typeclass;
767                         stset->subtyperefs[1].any = NULL; /* terminate */
768                 }
769         }
770
771         return true;
772
773 empty_set:
774         UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
775         return true;
776 }
777
778 unresolved_field *
779 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
780                                                 instruction *iptr,
781                                                 stackelement *stack)
782 {
783         unresolved_field *ref;
784         constant_FMIref *fieldref = NULL;
785         stackelement *instanceslot = NULL;
786         int type;
787         typeinfo tinfo;
788         typeinfo *tip = NULL;
789         typedesc *fd;
790
791 #ifdef RESOLVE_VERBOSE
792         fprintf(stderr,"create_unresolved_field\n");
793         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
794         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
795         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
796 #endif
797
798         ref = NEW(unresolved_field);
799         ref->flags = 0;
800         ref->referermethod = refmethod;
801
802         switch (iptr[0].opc) {
803                 case ICMD_PUTFIELD:
804                         ref->flags |= RESOLVE_PUTFIELD;
805                         instanceslot = stack->prev;
806                         tip = &(stack->typeinfo);
807                         fieldref = (constant_FMIref *) iptr[0].val.a;
808                         break;
809
810                 case ICMD_PUTFIELDCONST:
811                         ref->flags |= RESOLVE_PUTFIELD;
812                         instanceslot = stack;
813                         fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
814                         break;
815
816                 case ICMD_PUTSTATIC:
817                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
818                         fieldref = (constant_FMIref *) iptr[0].val.a;
819                         tip = &(stack->typeinfo);
820                         break;
821
822                 case ICMD_PUTSTATICCONST:
823                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
824                         fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
825                         break;
826
827                 case ICMD_GETFIELD:
828                         instanceslot = stack;
829                         fieldref = (constant_FMIref *) iptr[0].val.a;
830                         break;
831                         
832                 case ICMD_GETSTATIC:
833                         ref->flags |= RESOLVE_STATIC;
834                         fieldref = (constant_FMIref *) iptr[0].val.a;
835                         break;
836         }
837         
838         RESOLVE_ASSERT(fieldref);
839         RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
840         fd = fieldref->parseddesc.fd;
841         RESOLVE_ASSERT(fd);
842
843 #ifdef RESOLVE_VERBOSE
844         fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
845         fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
846         fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
847         fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
848         fputc('\n',stderr);
849         fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
850 #endif
851
852         ref->fieldref = fieldref;
853         
854         /* record subtype constraints for the instance type, if any */
855         if (instanceslot) {
856                 typeinfo *insttip;
857                 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
858                 
859                 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && 
860                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
861                 {   /* XXX clean up */
862                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
863                         classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a 
864                                                                                  : refmethod->class; /* XXX classrefs */
865                         RESOLVE_ASSERT(initclass->loaded && initclass->linked);
866                         TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
867                         insttip = &tinfo;
868                 }
869                 else {
870                         insttip = &(instanceslot->typeinfo);
871                 }
872                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
873                                         &(ref->instancetypes),insttip,fieldref->classref))
874                         return NULL;
875         }
876         else {
877                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
878         }
879         
880         /* record subtype constraints for the value type, if any */
881         type = fd->type;
882         if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
883                 if (!tip) {
884                         /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
885                         tip = &tinfo;
886                         if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
887                                 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
888                         }
889                         else
890                                 TYPEINFO_INIT_NULLTYPE(tinfo);
891                 }
892                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
893                                         &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
894                         return NULL;
895         }
896         else {
897                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
898         }
899
900         return ref;
901 }
902
903 unresolved_method *
904 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
905                                                  instruction *iptr,
906                                                  stackelement *stack)
907 {
908         unresolved_method *ref;
909         constant_FMIref *methodref;
910         stackelement *instanceslot = NULL;
911         stackelement *param;
912         methoddesc *md;
913         typeinfo tinfo;
914         int i,j;
915         int type;
916
917         methodref = (constant_FMIref *) iptr[0].val.a;
918         RESOLVE_ASSERT(methodref);
919         md = methodref->parseddesc.md;
920         RESOLVE_ASSERT(md);
921
922 #ifdef RESOLVE_VERBOSE
923         fprintf(stderr,"create_unresolved_method\n");
924         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
925         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
926         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
927         fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
928         fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
929         fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
930         fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
931 #endif
932
933         ref = NEW(unresolved_method);
934         ref->flags = 0;
935         ref->referermethod = refmethod;
936         ref->methodref = methodref;
937         ref->paramconstraints = NULL;
938
939         switch (iptr[0].opc) {
940                 case ICMD_INVOKESTATIC:
941                         ref->flags |= RESOLVE_STATIC;
942                         break;
943                 case ICMD_INVOKEVIRTUAL:
944                 case ICMD_INVOKESPECIAL:
945                 case ICMD_INVOKEINTERFACE:
946                         break;
947                 default:
948                         RESOLVE_ASSERT(false);
949         }
950
951         if ((ref->flags & RESOLVE_STATIC) == 0) {
952                 /* find the instance slot under all the parameter slots on the stack */
953                 instanceslot = stack;
954                 for (i=0; i<md->paramcount; ++i)
955                         instanceslot = instanceslot->prev;
956         }
957         
958         RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
959
960         /* record subtype constraints for the instance type, if any */
961         if (instanceslot) {
962                 typeinfo *tip;
963                 
964                 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
965                 
966                 if (iptr[0].opc == ICMD_INVOKESPECIAL && 
967                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
968                 {   /* XXX clean up */
969                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
970                         classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a 
971                                                                                  : refmethod->class; /* XXX classrefs */
972                         RESOLVE_ASSERT(initclass->loaded && initclass->linked);
973                         TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
974                         tip = &tinfo;
975                 }
976                 else {
977                         tip = &(instanceslot->typeinfo);
978                 }
979                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
980                                         &(ref->instancetypes),tip,methodref->classref))
981                         return NULL;
982         }
983         else {
984                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
985         }
986         
987         /* record subtype constraints for the parameter types, if any */
988         param = stack;
989         for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
990                 type = md->paramtypes[i].type;
991                 
992                 RESOLVE_ASSERT(param);
993                 RESOLVE_ASSERT(type == param->type);
994                 
995                 if (type == TYPE_ADR) {
996                         if (!ref->paramconstraints) {
997                                 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
998                                 for (j=md->paramcount-1; j>i; --j)
999                                         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1000                         }
1001                         RESOLVE_ASSERT(ref->paramconstraints);
1002                         if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1003                                                 ref->paramconstraints + i,&(param->typeinfo),
1004                                                 md->paramtypes[i].classref))
1005                                 return NULL;
1006                 }
1007                 else {
1008                         if (ref->paramconstraints)
1009                                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1010                 }
1011         }
1012
1013         return ref;
1014 }
1015
1016 /******************************************************************************/
1017 /* FREEING MEMORY                                                             */
1018 /******************************************************************************/
1019
1020 inline static void 
1021 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1022 {
1023         if (list) {
1024                 classref_or_classinfo *p = list;
1025
1026                 /* this is silly. we *only* need to count the elements for MFREE */
1027                 while ((p++)->any)
1028                         ;
1029                 MFREE(list,classref_or_classinfo,(p - list));
1030         }
1031 }
1032
1033 /* unresolved_field_free *******************************************************
1034  
1035    Free the memory used by an unresolved_field
1036   
1037    IN:
1038        ref..............the unresolved_field
1039
1040 *******************************************************************************/
1041
1042 void 
1043 unresolved_field_free(unresolved_field *ref)
1044 {
1045         RESOLVE_ASSERT(ref);
1046
1047         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1048         unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1049         FREE(ref,unresolved_field);
1050 }
1051
1052 /* unresolved_method_free ******************************************************
1053  
1054    Free the memory used by an unresolved_method
1055   
1056    IN:
1057        ref..............the unresolved_method
1058
1059 *******************************************************************************/
1060
1061 void 
1062 unresolved_method_free(unresolved_method *ref)
1063 {
1064         RESOLVE_ASSERT(ref);
1065
1066         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1067         if (ref->paramconstraints) {
1068                 int i;
1069                 int count = ref->methodref->parseddesc.md->paramcount;
1070
1071                 for (i=0; i<count; ++i)
1072                         unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1073                 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1074         }
1075         FREE(ref,unresolved_method);
1076 }
1077
1078 /******************************************************************************/
1079 /* DEBUG DUMPS                                                                */
1080 /******************************************************************************/
1081
1082 /* unresolved_subtype_set_debug_dump *******************************************
1083  
1084    Print debug info for unresolved_subtype_set to stream
1085   
1086    IN:
1087        stset............the unresolved_subtype_set
1088            file.............the stream
1089
1090 *******************************************************************************/
1091
1092 void
1093 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1094 {
1095         classref_or_classinfo *p;
1096         
1097         if (SUBTYPESET_IS_EMPTY(*stset)) {
1098                 fprintf(file,"        (empty)\n");
1099         }
1100         else {
1101                 p = stset->subtyperefs;
1102                 for (;p->any; ++p) {
1103                         if (IS_CLASSREF(*p)) {
1104                                 fprintf(file,"        ref: ");
1105                                 utf_fprint(file,p->ref->name);
1106                         }
1107                         else {
1108                                 fprintf(file,"        cls: ");
1109                                 utf_fprint(file,p->cls->name);
1110                         }
1111                         fputc('\n',file);
1112                 }
1113         }
1114 }
1115
1116 /* unresolved_field_debug_dump *************************************************
1117  
1118    Print debug info for unresolved_field to stream
1119   
1120    IN:
1121        ref..............the unresolved_field
1122            file.............the stream
1123
1124 *******************************************************************************/
1125
1126 void 
1127 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1128 {
1129         fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1130         if (ref) {
1131                 fprintf(file,"    referer   : ");
1132                 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1133                 fprintf(file,"    refmethod  : ");
1134                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1135                 fprintf(file,"    refmethodd : ");
1136                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1137                 fprintf(file,"    classname : ");
1138                 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1139                 fprintf(file,"    name      : ");
1140                 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1141                 fprintf(file,"    descriptor: ");
1142                 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1143                 fprintf(file,"    parseddesc: ");
1144                 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1145                 fprintf(file,"    flags     : %04x\n",ref->flags);
1146                 fprintf(file,"    instancetypes:\n");
1147                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1148                 fprintf(file,"    valueconstraints:\n");
1149                 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1150         }
1151 }
1152
1153 /* unresolved_method_debug_dump ************************************************
1154  
1155    Print debug info for unresolved_method to stream
1156   
1157    IN:
1158        ref..............the unresolved_method
1159            file.............the stream
1160
1161 *******************************************************************************/
1162
1163 void 
1164 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1165 {
1166         int i;
1167
1168         fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1169         if (ref) {
1170                 fprintf(file,"    referer   : ");
1171                 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1172                 fprintf(file,"    refmethod  : ");
1173                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1174                 fprintf(file,"    refmethodd : ");
1175                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1176                 fprintf(file,"    classname : ");
1177                 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1178                 fprintf(file,"    name      : ");
1179                 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1180                 fprintf(file,"    descriptor: ");
1181                 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1182                 fprintf(file,"    parseddesc: ");
1183                 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1184                 fprintf(file,"    flags     : %04x\n",ref->flags);
1185                 fprintf(file,"    instancetypes:\n");
1186                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1187                 fprintf(file,"    paramconstraints:\n");
1188                 if (ref->paramconstraints) {
1189                         for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1190                                 fprintf(file,"      param %d:\n",i);
1191                                 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1192                         }
1193                 } 
1194                 else {
1195                         fprintf(file,"      (empty)\n");
1196                 }
1197         }
1198 }
1199
1200 /*
1201  * These are local overrides for various environment variables in Emacs.
1202  * Please do not remove this and leave it at the end of the file, where
1203  * Emacs will automagically detect them.
1204  * ---------------------------------------------------------------------
1205  * Local variables:
1206  * mode: c
1207  * indent-tabs-mode: t
1208  * c-basic-offset: 4
1209  * tab-width: 4
1210  * End:
1211  * vim:noexpandtab:sw=4:ts=4:
1212  */
1213