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