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