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