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