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