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