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