link class in resolve_field/resolve_method
[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 2227 2005-04-05 23:00:37Z 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                           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,
612                            resolve_mode_t mode,
613                            methodinfo **result)
614 {
615         classinfo *referer;
616         classinfo *container;
617         classinfo *declarer;
618         methodinfo *mi;
619         typedesc *paramtypes;
620         int instancecount;
621         int i;
622         bool checked;
623         
624         RESOLVE_ASSERT(ref);
625         RESOLVE_ASSERT(result);
626         RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
627
628 #ifdef RESOLVE_VERBOSE
629         unresolved_method_debug_dump(ref,stderr);
630 #endif
631
632         *result = NULL;
633
634         /* the class containing the reference */
635         referer = ref->methodref->classref->referer;
636         RESOLVE_ASSERT(referer);
637
638         /* first we must resolve the class containg the method */
639         if (!resolve_class_from_name(referer,ref->referermethod,
640                                            ref->methodref->classref->name,mode,true,&container))
641         {
642                 /* the class reference could not be resolved */
643                 return false; /* exception */
644         }
645         if (!container)
646                 return true; /* be lazy */
647
648         RESOLVE_ASSERT(container);
649
650         /* now we must find the declaration of the method in `container`
651          * or one of its superclasses */
652
653         if ((container->flags & ACC_INTERFACE) != 0) {
654                 mi = class_resolveinterfacemethod(container,
655                                                                               ref->methodref->name,ref->methodref->descriptor,
656                                                                               referer,true);
657         }
658         else {
659                 mi = class_resolveclassmethod(container,
660                                                                           ref->methodref->name,ref->methodref->descriptor,
661                                                                           referer,true);
662         }
663         if (!mi)
664                 return false; /* exception */ /* XXX set exceptionptr? */
665
666         /* { the method reference has been resolved } */
667         declarer = mi->class;
668         RESOLVE_ASSERT(declarer);
669
670         /* check static */
671         if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
672                 /* a static method is accessed via an instance, or vice versa */
673                 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
674                                 (mi->flags & ACC_STATIC) ? "static method called via instance"
675                                                          : "instance method called without instance");
676                 return false; /* exception */
677         }
678
679         /* for non-static methods we have to check the constraints on the instance type */
680         if ((ref->flags & RESOLVE_STATIC) == 0) {
681                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
682                                                                                    &(ref->instancetypes),
683                                                                                    CLASSREF_OR_CLASSINFO(container),
684                                                                                    false,
685                                                                                    mode,
686                                                                                    resolveLinkageError,&checked))
687                 {
688                         return false; /* exception */
689                 }
690                 if (!checked)
691                         return true; /* be lazy */
692                 instancecount = 1;
693         }
694         else {
695                 instancecount = 0;
696         }
697
698         /* check subtype constraints for TYPE_ADR parameters */
699         RESOLVE_ASSERT(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
700         paramtypes = mi->parseddesc->paramtypes;
701         
702         for (i=0; i<mi->parseddesc->paramcount; ++i) {
703                 if (paramtypes[i].type == TYPE_ADR) {
704                         if (ref->paramconstraints) {
705                                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
706                                                         ref->paramconstraints + i,
707                                                         CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
708                                                         false,
709                                                         mode,
710                                                         resolveLinkageError,&checked))
711                                 {
712                                         return false; /* exception */
713                                 }
714                                 if (!checked)
715                                         return true; /* be lazy */
716                         }
717                 }
718         }
719
720         /* check access rights */
721         if (!is_accessible_member(referer,declarer,mi->flags)) {
722                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
723                                 "method is not accessible XXX add message");
724                 return false; /* exception */
725         }
726
727         /* check protected access */
728         if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
729                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
730                                                                                    &(ref->instancetypes),
731                                                                                    CLASSREF_OR_CLASSINFO(referer),
732                                                                                    false,
733                                                                                    mode,
734                                                                                    resolveIllegalAccessError,&checked))
735                 {
736                         return false; /* exception */
737                 }
738                 if (!checked)
739                         return true; /* be lazy */
740         }
741
742         /* impose loading constraints on parameters (including instance) */
743         paramtypes = mi->parseddesc->paramtypes - instancecount;
744         for (i=0; i<mi->parseddesc->paramcount + instancecount; ++i) {
745                 if (i<instancecount || paramtypes[i].type == TYPE_ADR) {
746                         utf *name;
747                         
748                         if (i < instancecount)
749                                 name = container->name; /* XXX should this be declarer->name? */
750                         else
751                                 name = paramtypes[i].classref->name;
752                         
753                         if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
754                                 return false; /* exception */
755                 }
756         }
757
758         /* impose loading constraing onto return type */
759         if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
760                 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
761                                 ref->methodref->parseddesc.md->returntype.classref->name))
762                         return false; /* exception */
763         }
764
765         /* succeed */
766         *result = mi;
767         return true;
768 }
769
770 /******************************************************************************/
771 /* CREATING THE DATA STRUCTURES                                               */
772 /******************************************************************************/
773
774 static bool
775 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
776                 unresolved_subtype_set *stset,typeinfo *tinfo,
777                 constant_classref *declaredtype)
778 {
779         int count;
780         int i;
781         
782         RESOLVE_ASSERT(stset);
783         RESOLVE_ASSERT(tinfo);
784
785 #ifdef RESOLVE_VERBOSE
786         fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
787 #ifdef TYPEINFO_DEBUG
788         /*typeinfo_print(stderr,tinfo,4);*/
789         fprintf(stderr,"\n");
790 #endif
791         fprintf(stderr,"    declared type:");utf_fprint(stderr,declaredtype->name);
792         fprintf(stderr,"\n");
793 #endif
794
795         if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
796                 *exceptionptr = new_verifyerror(refmethod,
797                                 "Invalid use of returnAddress");
798                 return false;
799         }
800
801         if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
802                 *exceptionptr = new_verifyerror(refmethod,
803                                 "Invalid use of uninitialized object");
804                 return false;
805         }
806
807         /* the nulltype is always assignable (XXX for reversed?) */
808         if (TYPEINFO_IS_NULLTYPE(*tinfo))
809                 goto empty_set;
810
811         /* every type is assignable to (BOOTSTRAP)java.lang.Object */
812         if (declaredtype->name == utf_java_lang_Object
813                         && referer->classloader == NULL)
814         {
815                 goto empty_set;
816         }
817
818         if (tinfo->merged) {
819                 count = tinfo->merged->count;
820                 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
821                 for (i=0; i<count; ++i) {
822                         stset->subtyperefs[i] = tinfo->merged->list[i];
823                 }
824                 stset->subtyperefs[count].any = NULL; /* terminate */
825         }
826         else {
827                 if ((IS_CLASSREF(tinfo->typeclass)
828                                         ? tinfo->typeclass.ref->name 
829                                         : tinfo->typeclass.cls->name) == declaredtype->name)
830                 {
831                         goto empty_set;
832                 }
833                 else {
834                         stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
835                         stset->subtyperefs[0] = tinfo->typeclass;
836                         stset->subtyperefs[1].any = NULL; /* terminate */
837                 }
838         }
839
840         return true;
841
842 empty_set:
843         UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
844         return true;
845 }
846
847 unresolved_class *
848 create_unresolved_class(methodinfo *refmethod,
849                                                 constant_classref *classref,
850                                                 typeinfo *valuetype)
851 {
852         unresolved_class *ref;
853         
854         RESOLVE_ASSERT(ref);
855         
856 #ifdef RESOLVE_VERBOSE
857         fprintf(stderr,"create_unresolved_class\n");
858         fprintf(stderr,"    referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
859         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
860         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
861         fprintf(stderr,"    name   : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
862 #endif
863
864         ref = NEW(unresolved_class);
865         ref->classref = classref;
866         ref->referermethod = refmethod;
867
868         if (valuetype) {
869                 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
870                                         &(ref->subtypeconstraints),valuetype,classref))
871                         return NULL;
872         }
873         else {
874                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
875         }
876
877         return ref;
878 }
879
880 unresolved_field *
881 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
882                                                 instruction *iptr,
883                                                 stackelement *stack)
884 {
885         unresolved_field *ref;
886         constant_FMIref *fieldref = NULL;
887         stackelement *instanceslot = NULL;
888         int type;
889         typeinfo tinfo;
890         typeinfo *tip = NULL;
891         typedesc *fd;
892
893 #ifdef RESOLVE_VERBOSE
894         fprintf(stderr,"create_unresolved_field\n");
895         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
896         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
897         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
898 #endif
899
900         ref = NEW(unresolved_field);
901         ref->flags = 0;
902         ref->referermethod = refmethod;
903
904         switch (iptr[0].opc) {
905                 case ICMD_PUTFIELD:
906                         ref->flags |= RESOLVE_PUTFIELD;
907                         if (stack) {
908                                 instanceslot = stack->prev;
909                                 tip = &(stack->typeinfo);
910                         }
911                         fieldref = (constant_FMIref *) iptr[0].val.a;
912                         break;
913
914                 case ICMD_PUTFIELDCONST:
915                         ref->flags |= RESOLVE_PUTFIELD;
916                         if (stack) instanceslot = stack;
917                         fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
918                         break;
919
920                 case ICMD_PUTSTATIC:
921                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
922                         fieldref = (constant_FMIref *) iptr[0].val.a;
923                         if (stack) tip = &(stack->typeinfo);
924                         break;
925
926                 case ICMD_PUTSTATICCONST:
927                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
928                         fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
929                         break;
930
931                 case ICMD_GETFIELD:
932                         if (stack) instanceslot = stack;
933                         fieldref = (constant_FMIref *) iptr[0].val.a;
934                         break;
935                         
936                 case ICMD_GETSTATIC:
937                         ref->flags |= RESOLVE_STATIC;
938                         fieldref = (constant_FMIref *) iptr[0].val.a;
939                         break;
940         }
941         
942         RESOLVE_ASSERT(fieldref);
943         RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
944         fd = fieldref->parseddesc.fd;
945         RESOLVE_ASSERT(fd);
946
947 #ifdef RESOLVE_VERBOSE
948         fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
949         fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
950         fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
951         fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
952         fputc('\n',stderr);
953         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
954 #endif
955
956         ref->fieldref = fieldref;
957         
958         /* record subtype constraints for the instance type, if any */
959         if (instanceslot) {
960                 typeinfo *insttip;
961                 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
962                 
963                 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && 
964                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
965                 {   /* XXX clean up */
966                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
967                         classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a 
968                                                                                  : refmethod->class; /* XXX classrefs */
969                         RESOLVE_ASSERT(initclass->loaded && initclass->linked);
970                         TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
971                         insttip = &tinfo;
972                 }
973                 else {
974                         insttip = &(instanceslot->typeinfo);
975                 }
976                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
977                                         &(ref->instancetypes),insttip,fieldref->classref))
978                         return NULL;
979         }
980         else {
981                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
982         }
983         
984         /* record subtype constraints for the value type, if any */
985         type = fd->type;
986         if (stack && type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
987                 if (!tip) {
988                         /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
989                         tip = &tinfo;
990                         if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
991                                 RESOLVE_ASSERT(class_java_lang_String);
992                                 RESOLVE_ASSERT(class_java_lang_String->loaded);
993                                 RESOLVE_ASSERT(class_java_lang_String->linked);
994                                 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
995                         }
996                         else
997                                 TYPEINFO_INIT_NULLTYPE(tinfo);
998                 }
999                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1000                                         &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
1001                         return NULL;
1002         }
1003         else {
1004                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1005         }
1006
1007         return ref;
1008 }
1009
1010 unresolved_method *
1011 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
1012                                                  instruction *iptr,
1013                                                  stackelement *stack)
1014 {
1015         unresolved_method *ref;
1016         constant_FMIref *methodref;
1017         stackelement *instanceslot = NULL;
1018         stackelement *param;
1019         methoddesc *md;
1020         typeinfo tinfo;
1021         int i,j;
1022         int type;
1023
1024         methodref = (constant_FMIref *) iptr[0].val.a;
1025         RESOLVE_ASSERT(methodref);
1026         md = methodref->parseddesc.md;
1027         RESOLVE_ASSERT(md);
1028
1029 #ifdef RESOLVE_VERBOSE
1030         fprintf(stderr,"create_unresolved_method\n");
1031         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1032         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1033         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1034         fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1035         fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1036         fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1037         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1038 #endif
1039
1040         ref = NEW(unresolved_method);
1041         ref->flags = 0;
1042         ref->referermethod = refmethod;
1043         ref->methodref = methodref;
1044         ref->paramconstraints = NULL;
1045
1046         switch (iptr[0].opc) {
1047                 case ICMD_INVOKESTATIC:
1048                         ref->flags |= RESOLVE_STATIC;
1049                         break;
1050                 case ICMD_INVOKEVIRTUAL:
1051                 case ICMD_INVOKESPECIAL:
1052                 case ICMD_INVOKEINTERFACE:
1053                         break;
1054                 default:
1055                         RESOLVE_ASSERT(false);
1056         }
1057
1058         if (stack && (ref->flags & RESOLVE_STATIC) == 0) {
1059                 /* find the instance slot under all the parameter slots on the stack */
1060                 instanceslot = stack;
1061                 for (i=0; i<md->paramcount; ++i)
1062                         instanceslot = instanceslot->prev;
1063         }
1064         
1065         RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1066
1067         /* record subtype constraints for the instance type, if any */
1068         if (instanceslot) {
1069                 typeinfo *tip;
1070                 
1071                 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
1072                 
1073                 if (iptr[0].opc == ICMD_INVOKESPECIAL && 
1074                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1075                 {   /* XXX clean up */
1076                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1077                         classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a 
1078                                                                                  : refmethod->class; /* XXX classrefs */
1079                         RESOLVE_ASSERT(initclass->loaded && initclass->linked);
1080                         TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1081                         tip = &tinfo;
1082                 }
1083                 else {
1084                         tip = &(instanceslot->typeinfo);
1085                 }
1086                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1087                                         &(ref->instancetypes),tip,methodref->classref))
1088                         return NULL;
1089         }
1090         else {
1091                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1092         }
1093         
1094         /* record subtype constraints for the parameter types, if any */
1095         if (stack) {
1096                 param = stack;
1097                 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
1098                         type = md->paramtypes[i].type;
1099                         
1100                         RESOLVE_ASSERT(param);
1101                         RESOLVE_ASSERT(type == param->type);
1102                         
1103                         if (type == TYPE_ADR) {
1104                                 if (!ref->paramconstraints) {
1105                                         ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1106                                         for (j=md->paramcount-1; j>i; --j)
1107                                                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1108                                 }
1109                                 RESOLVE_ASSERT(ref->paramconstraints);
1110                                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1111                                                         ref->paramconstraints + i,&(param->typeinfo),
1112                                                         md->paramtypes[i].classref))
1113                                         return NULL;
1114                         }
1115                         else {
1116                                 if (ref->paramconstraints)
1117                                         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1118                         }
1119                 }
1120         }
1121
1122         return ref;
1123 }
1124
1125 /******************************************************************************/
1126 /* FREEING MEMORY                                                             */
1127 /******************************************************************************/
1128
1129 inline static void 
1130 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1131 {
1132         if (list) {
1133                 classref_or_classinfo *p = list;
1134
1135                 /* this is silly. we *only* need to count the elements for MFREE */
1136                 while ((p++)->any)
1137                         ;
1138                 MFREE(list,classref_or_classinfo,(p - list));
1139         }
1140 }
1141
1142 /* unresolved_class_free *******************************************************
1143  
1144    Free the memory used by an unresolved_class
1145   
1146    IN:
1147        ref..............the unresolved_class
1148
1149 *******************************************************************************/
1150
1151 void 
1152 unresolved_class_free(unresolved_class *ref)
1153 {
1154         RESOLVE_ASSERT(ref);
1155
1156         unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
1157         FREE(ref,unresolved_class);
1158 }
1159
1160 /* unresolved_field_free *******************************************************
1161  
1162    Free the memory used by an unresolved_field
1163   
1164    IN:
1165        ref..............the unresolved_field
1166
1167 *******************************************************************************/
1168
1169 void 
1170 unresolved_field_free(unresolved_field *ref)
1171 {
1172         RESOLVE_ASSERT(ref);
1173
1174         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1175         unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1176         FREE(ref,unresolved_field);
1177 }
1178
1179 /* unresolved_method_free ******************************************************
1180  
1181    Free the memory used by an unresolved_method
1182   
1183    IN:
1184        ref..............the unresolved_method
1185
1186 *******************************************************************************/
1187
1188 void 
1189 unresolved_method_free(unresolved_method *ref)
1190 {
1191         RESOLVE_ASSERT(ref);
1192
1193         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1194         if (ref->paramconstraints) {
1195                 int i;
1196                 int count = ref->methodref->parseddesc.md->paramcount;
1197
1198                 for (i=0; i<count; ++i)
1199                         unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1200                 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1201         }
1202         FREE(ref,unresolved_method);
1203 }
1204
1205 /******************************************************************************/
1206 /* DEBUG DUMPS                                                                */
1207 /******************************************************************************/
1208
1209 /* unresolved_subtype_set_debug_dump *******************************************
1210  
1211    Print debug info for unresolved_subtype_set to stream
1212   
1213    IN:
1214        stset............the unresolved_subtype_set
1215            file.............the stream
1216
1217 *******************************************************************************/
1218
1219 void
1220 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1221 {
1222         classref_or_classinfo *p;
1223         
1224         if (SUBTYPESET_IS_EMPTY(*stset)) {
1225                 fprintf(file,"        (empty)\n");
1226         }
1227         else {
1228                 p = stset->subtyperefs;
1229                 for (;p->any; ++p) {
1230                         if (IS_CLASSREF(*p)) {
1231                                 fprintf(file,"        ref: ");
1232                                 utf_fprint(file,p->ref->name);
1233                         }
1234                         else {
1235                                 fprintf(file,"        cls: ");
1236                                 utf_fprint(file,p->cls->name);
1237                         }
1238                         fputc('\n',file);
1239                 }
1240         }
1241 }
1242
1243 /* unresolved_class_debug_dump *************************************************
1244  
1245    Print debug info for unresolved_class to stream
1246   
1247    IN:
1248        ref..............the unresolved_class
1249            file.............the stream
1250
1251 *******************************************************************************/
1252
1253 void 
1254 unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
1255 {
1256         fprintf(file,"unresolved_class(%p):\n",(void *)ref);
1257         if (ref) {
1258                 fprintf(file,"    referer   : ");
1259                 utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
1260                 fprintf(file,"    refmethod  : ");
1261                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1262                 fprintf(file,"    refmethodd : ");
1263                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1264                 fprintf(file,"    classname : ");
1265                 utf_fprint(file,ref->classref->name); fputc('\n',file);
1266                 fprintf(file,"    subtypeconstraints:\n");
1267                 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
1268         }
1269 }
1270
1271 /* unresolved_field_debug_dump *************************************************
1272  
1273    Print debug info for unresolved_field to stream
1274   
1275    IN:
1276        ref..............the unresolved_field
1277            file.............the stream
1278
1279 *******************************************************************************/
1280
1281 void 
1282 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1283 {
1284         fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1285         if (ref) {
1286                 fprintf(file,"    referer   : ");
1287                 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1288                 fprintf(file,"    refmethod  : ");
1289                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1290                 fprintf(file,"    refmethodd : ");
1291                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1292                 fprintf(file,"    classname : ");
1293                 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1294                 fprintf(file,"    name      : ");
1295                 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1296                 fprintf(file,"    descriptor: ");
1297                 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1298                 fprintf(file,"    parseddesc: ");
1299                 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1300                 fprintf(file,"    flags     : %04x\n",ref->flags);
1301                 fprintf(file,"    instancetypes:\n");
1302                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1303                 fprintf(file,"    valueconstraints:\n");
1304                 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1305         }
1306 }
1307
1308 /* unresolved_method_debug_dump ************************************************
1309  
1310    Print debug info for unresolved_method to stream
1311   
1312    IN:
1313        ref..............the unresolved_method
1314            file.............the stream
1315
1316 *******************************************************************************/
1317
1318 void 
1319 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1320 {
1321         int i;
1322
1323         fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1324         if (ref) {
1325                 fprintf(file,"    referer   : ");
1326                 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1327                 fprintf(file,"    refmethod  : ");
1328                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1329                 fprintf(file,"    refmethodd : ");
1330                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1331                 fprintf(file,"    classname : ");
1332                 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1333                 fprintf(file,"    name      : ");
1334                 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1335                 fprintf(file,"    descriptor: ");
1336                 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1337                 fprintf(file,"    parseddesc: ");
1338                 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1339                 fprintf(file,"    flags     : %04x\n",ref->flags);
1340                 fprintf(file,"    instancetypes:\n");
1341                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1342                 fprintf(file,"    paramconstraints:\n");
1343                 if (ref->paramconstraints) {
1344                         for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1345                                 fprintf(file,"      param %d:\n",i);
1346                                 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1347                         }
1348                 } 
1349                 else {
1350                         fprintf(file,"      (empty)\n");
1351                 }
1352         }
1353 }
1354
1355 /*
1356  * These are local overrides for various environment variables in Emacs.
1357  * Please do not remove this and leave it at the end of the file, where
1358  * Emacs will automagically detect them.
1359  * ---------------------------------------------------------------------
1360  * Local variables:
1361  * mode: c
1362  * indent-tabs-mode: t
1363  * c-basic-offset: 4
1364  * tab-width: 4
1365  * End:
1366  * vim:noexpandtab:sw=4:ts=4:
1367  */
1368