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