Merged revisions 7441-7480 via svnmerge from
[cacao.git] / src / vm / jit / verify / icmds.c
1 /* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Edwin Steiner
28
29    Changes:
30
31    $Id$
32
33 */
34
35 #if 0 /* (needed for code examples in the following comment) */
36 /******************************************************************************/
37 /* This file contains ICMD-specific code for type checking and type
38  * inference. It is an input file for the verifier generator
39  * (src/vm/jit/verify/generate.pl). The verifier generator creates
40  * code for three compiler passes:
41  *     - stack-based type-infering verification
42  *     - vasiables-based type-infering verification
43  *     - type inference pass (no verification - used for optimizing compiler)
44  *
45  * The rest of this file must consist of "case" clauses starting in
46  * the first column. Each clause can be marked with tags like this:
47  *
48  */          case ICMD_CONSTANT: /* {TAG, TAG, ...} */
49 /*
50  * This must be on one line. The following tags are defined:
51  *     STACKBASED..........use this clause for the stack-based verifier
52  *     VARIABLESBASED......use this clause for the variables-based verifier
53  *     TYPEINFERER.........use this clause for the type inference pass
54  *     ALL.................use for all passes
55  *
56  * If no tag is specified, {STACKBASED,VARIABLESBASED} is assumed.
57  *
58  * There are also tags that can be used inside a clause like this:
59  *
60  */          /* {TAG} */
61 /*
62  * The following tags are defined within clauses:
63  *     RESULTNOW...........generate code for modelling the stack action
64  *                         _before_ the user-defined code in the clause
65  *                         (Default is to model the stack action afterwards.)
66  *
67  * The following macros are pre-defined:
68  *
69  *     TYPECHECK_STACKBASED.......iff compiling the stack-based verifier
70  *     TYPECHECK_VARIABLESBASED...iff compiling the variables-based verifier
71  *     TYPECHECK_TYPEINFERER......iff compiling the type inference pass
72  *
73 /******************************************************************************/
74 #endif /* (end #if 0) */
75
76
77 /* this marker is needed by generate.pl: */
78 /* {START_OF_CODE} */
79
80         /****************************************/
81         /* MOVE/COPY                            */
82
83         /* We just need to copy the typeinfo */
84         /* for slots containing addresses.   */
85
86         /* (These are only used by the variables based verifier.) */
87
88 case ICMD_MOVE: /* {VARIABLESBASED,TYPEINFERER} */
89 case ICMD_COPY: /* {VARIABLESBASED,TYPEINFERER} */
90         TYPECHECK_COUNT(stat_ins_stack);
91         COPYTYPE(IPTR->s1, IPTR->dst);
92         DST->type = OP1->type;
93         break;
94
95         /****************************************/
96         /* LOADING ADDRESS FROM VARIABLE        */
97
98 case ICMD_ALOAD: /* {ALL} */
99         TYPECHECK_COUNT(stat_ins_aload);
100
101 #if !defined(TYPECHECK_TYPEINFERER)
102         /* loading a returnAddress is not allowed */
103         if (!TYPEDESC_IS_REFERENCE(*OP1)) {
104                 VERIFY_ERROR("illegal instruction: ALOAD loading non-reference");
105         }
106 #endif
107         TYPEINFO_COPY(OP1->typeinfo,DST->typeinfo);
108         break;
109
110         /****************************************/
111         /* STORING ADDRESS TO VARIABLE          */
112
113 case ICMD_ASTORE: /* {ALL} */
114         TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
115         break;
116
117         /****************************************/
118         /* LOADING ADDRESS FROM ARRAY           */
119
120 case ICMD_AALOAD: /* {ALL} */
121 #if !defined(TYPECHECK_TYPEINFERER)
122         if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
123                 VERIFY_ERROR("illegal instruction: AALOAD on non-reference array");
124 #endif
125
126         if (!typeinfo_init_component(&OP1->typeinfo,&DST->typeinfo))
127                 EXCEPTION;
128         break;
129
130         /****************************************/
131         /* FIELD ACCESS                         */
132
133 case ICMD_PUTFIELD: /* {STACKBASED} */
134         CHECK_STACK_DEPTH(2);
135         if (!IS_CAT1(stack[0])) {
136                 CHECK_STACK_DEPTH(3);
137                 stack -= 1;
138         }
139         CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
140         stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
141         if (stack == NULL)
142                 EXCEPTION;
143         break;
144
145 case ICMD_PUTSTATIC: /* {STACKBASED} */
146         CHECK_STACK_DEPTH(1);
147         if (!IS_CAT1(stack[0])) {
148                 /* (stack depth >= 2 is guaranteed) */
149                 stack -= 1;
150         }
151         stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
152         if (stack == NULL)
153                 EXCEPTION;
154         break;
155
156 case ICMD_GETFIELD: /* {STACKBASED} */
157         CHECK_STACK_TYPE(stack[0], TYPE_ADR);
158         stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
159         if (stack == NULL)
160                 EXCEPTION;
161         break;
162
163 case ICMD_GETSTATIC:      /* {STACKBASED} */
164         stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
165         if (stack == NULL)
166                 EXCEPTION;
167         break;
168
169 case ICMD_PUTFIELD:       /* {VARIABLESBASED} */
170         if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
171                 return false;
172         maythrow = true;
173         break;
174
175 case ICMD_PUTSTATIC:      /* {VARIABLESBASED} */
176         if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
177                 return false;
178         maythrow = true;
179         break;
180
181 case ICMD_PUTFIELDCONST:  /* {VARIABLESBASED} */
182         /* XXX this mess will go away with const operands */
183         INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
184         constvalue.type = fieldref->parseddesc.fd->type;
185         if (IS_ADR_TYPE(constvalue.type)) {
186                 if (state->iptr->sx.val.anyptr) {
187                         classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
188                                 ? class_java_lang_Class : class_java_lang_String;
189                         assert(cc);
190                         assert(cc->state & CLASS_LINKED);
191                         typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
192                 }
193                 else {
194                         TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
195                 }
196         }
197         if (!handle_fieldaccess(state, VAROP(iptr->s1), &constvalue))
198                 return false;
199         maythrow = true;
200         break;
201
202 case ICMD_PUTSTATICCONST: /* {VARIABLESBASED} */
203         /* XXX this mess will go away with const operands */
204         INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
205         constvalue.type = fieldref->parseddesc.fd->type;
206         if (IS_ADR_TYPE(constvalue.type)) {
207                 if (state->iptr->sx.val.anyptr) {
208                         classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
209                                 ? class_java_lang_Class : class_java_lang_String;
210                         assert(cc);
211                         assert(cc->state & CLASS_LINKED);
212                         typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
213                 }
214                 else {
215                         TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
216                 }
217         }
218         if (!handle_fieldaccess(state, NULL, &constvalue))
219                 return false;
220         maythrow = true;
221         break;
222
223 case ICMD_GETFIELD:       /* {VARIABLESBASED,TYPEINFERER} */
224         if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
225                 return false;
226         maythrow = true;
227         break;
228
229 case ICMD_GETSTATIC:      /* {VARIABLESBASED,TYPEINFERER} */
230         if (!handle_fieldaccess(state, NULL, NULL))
231                 return false;
232         maythrow = true;
233         break;
234
235         /****************************************/
236         /* PRIMITIVE ARRAY ACCESS               */
237
238 case ICMD_ARRAYLENGTH:
239         if (!TYPEINFO_MAYBE_ARRAY(OP1->typeinfo)
240                         && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
241                 VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
242         break;
243
244 case ICMD_BALOAD:
245         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
246                         && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
247                 VERIFY_ERROR("Array type mismatch");
248         break;
249
250 case ICMD_CALOAD:
251         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
252                 VERIFY_ERROR("Array type mismatch");
253         break;
254
255 case ICMD_DALOAD:
256         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
257                 VERIFY_ERROR("Array type mismatch");
258         break;
259
260 case ICMD_FALOAD:
261         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
262                 VERIFY_ERROR("Array type mismatch");
263         break;
264
265 case ICMD_IALOAD:
266         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
267                 VERIFY_ERROR("Array type mismatch");
268         break;
269
270 case ICMD_SALOAD:
271         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
272                 VERIFY_ERROR("Array type mismatch");
273         break;
274
275 case ICMD_LALOAD:
276         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
277                 VERIFY_ERROR("Array type mismatch");
278         break;
279
280 case ICMD_BASTORE:
281         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
282                         && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
283                 VERIFY_ERROR("Array type mismatch");
284         break;
285
286 case ICMD_CASTORE:
287         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
288                 VERIFY_ERROR("Array type mismatch");
289         break;
290
291 case ICMD_DASTORE:
292         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
293                 VERIFY_ERROR("Array type mismatch");
294         break;
295
296 case ICMD_FASTORE:
297         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
298                 VERIFY_ERROR("Array type mismatch");
299         break;
300
301 case ICMD_IASTORE:
302         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
303                 VERIFY_ERROR("Array type mismatch");
304         break;
305
306 case ICMD_SASTORE:
307         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
308                 VERIFY_ERROR("Array type mismatch");
309         break;
310
311 case ICMD_LASTORE:
312         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
313                 VERIFY_ERROR("Array type mismatch");
314         break;
315
316 case ICMD_AASTORE:
317         /* we just check the basic input types and that the           */
318         /* destination is an array of references. Assignability to    */
319         /* the actual array must be checked at runtime, each time the */
320         /* instruction is performed. (See builtin_canstore.)          */
321         if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
322                 VERIFY_ERROR("illegal instruction: AASTORE to non-reference array");
323         break;
324
325 case ICMD_IASTORECONST:
326         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_INT))
327                 VERIFY_ERROR("Array type mismatch");
328         break;
329
330 case ICMD_LASTORECONST:
331         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_LONG))
332                 VERIFY_ERROR("Array type mismatch");
333         break;
334
335 case ICMD_BASTORECONST:
336         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BOOLEAN)
337                         && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BYTE))
338                 VERIFY_ERROR("Array type mismatch");
339         break;
340
341 case ICMD_CASTORECONST:
342         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_CHAR))
343                 VERIFY_ERROR("Array type mismatch");
344         break;
345
346 case ICMD_SASTORECONST:
347         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_SHORT))
348                 VERIFY_ERROR("Array type mismatch");
349         break;
350
351         /****************************************/
352         /* ADDRESS CONSTANTS                    */
353
354 case ICMD_ACONST: /* {ALL} */
355         if (IPTR->flags.bits & INS_FLAG_CLASS) {
356                 /* a java.lang.Class reference */
357                 TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
358         }
359         else {
360                 if (IPTR->sx.val.anyptr == NULL)
361                         TYPEINFO_INIT_NULLTYPE(DST->typeinfo);
362                 else {
363                         /* string constant (or constant for builtin function) */
364                         typeinfo_init_classinfo(&(DST->typeinfo),class_java_lang_String);
365                 }
366         }
367         break;
368
369         /****************************************/
370         /* CHECKCAST AND INSTANCEOF             */
371
372 case ICMD_CHECKCAST: /* {ALL} */
373 #if !defined(TYPECHECK_TYPEINFERER)
374         /* returnAddress is not allowed */
375         if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
376                 VERIFY_ERROR("Illegal instruction: CHECKCAST on non-reference");
377 #endif
378
379     /* XXX only if narrower */
380         if (!typeinfo_init_class(&(DST->typeinfo),IPTR->sx.s23.s3.c))
381                 EXCEPTION;
382         break;
383
384 case ICMD_INSTANCEOF:
385         /* returnAddress is not allowed */
386         if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
387                 VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
388
389         /* XXX should propagate type information to the following if-branches */
390         break;
391
392         /****************************************/
393         /* BRANCH INSTRUCTIONS                  */
394
395 case ICMD_GOTO:            /* {ALL} */
396 case ICMD_IFNULL:          /* {ALL} */
397 case ICMD_IFNONNULL:       /* {ALL} */
398 case ICMD_IFEQ:            /* {ALL} */
399 case ICMD_IFNE:            /* {ALL} */
400 case ICMD_IFLT:            /* {ALL} */
401 case ICMD_IFGE:            /* {ALL} */
402 case ICMD_IFGT:            /* {ALL} */
403 case ICMD_IFLE:            /* {ALL} */
404 case ICMD_IF_ICMPEQ:       /* {ALL} */
405 case ICMD_IF_ICMPNE:       /* {ALL} */
406 case ICMD_IF_ICMPLT:       /* {ALL} */
407 case ICMD_IF_ICMPGE:       /* {ALL} */
408 case ICMD_IF_ICMPGT:       /* {ALL} */
409 case ICMD_IF_ICMPLE:       /* {ALL} */
410 case ICMD_IF_ACMPEQ:       /* {ALL} */
411 case ICMD_IF_ACMPNE:       /* {ALL} */
412
413 case ICMD_IF_LEQ:          /* {ALL} */
414 case ICMD_IF_LNE:          /* {ALL} */
415 case ICMD_IF_LLT:          /* {ALL} */
416 case ICMD_IF_LGE:          /* {ALL} */
417 case ICMD_IF_LGT:          /* {ALL} */
418 case ICMD_IF_LLE:          /* {ALL} */
419
420 case ICMD_IF_LCMPEQ:       /* {ALL} */
421 case ICMD_IF_LCMPNE:       /* {ALL} */
422 case ICMD_IF_LCMPLT:       /* {ALL} */
423 case ICMD_IF_LCMPGE:       /* {ALL} */
424 case ICMD_IF_LCMPGT:       /* {ALL} */
425 case ICMD_IF_LCMPLE:       /* {ALL} */
426
427 case ICMD_IF_FCMPEQ:       /* {ALL} */
428 case ICMD_IF_FCMPNE:       /* {ALL} */
429
430 case ICMD_IF_FCMPL_LT:     /* {ALL} */
431 case ICMD_IF_FCMPL_GE:     /* {ALL} */
432 case ICMD_IF_FCMPL_GT:     /* {ALL} */
433 case ICMD_IF_FCMPL_LE:     /* {ALL} */
434
435 case ICMD_IF_FCMPG_LT:     /* {ALL} */
436 case ICMD_IF_FCMPG_GE:     /* {ALL} */
437 case ICMD_IF_FCMPG_GT:     /* {ALL} */
438 case ICMD_IF_FCMPG_LE:     /* {ALL} */
439
440 case ICMD_IF_DCMPEQ:       /* {ALL} */
441 case ICMD_IF_DCMPNE:       /* {ALL} */
442
443 case ICMD_IF_DCMPL_LT:     /* {ALL} */
444 case ICMD_IF_DCMPL_GE:     /* {ALL} */
445 case ICMD_IF_DCMPL_GT:     /* {ALL} */
446 case ICMD_IF_DCMPL_LE:     /* {ALL} */
447
448 case ICMD_IF_DCMPG_LT:     /* {ALL} */
449 case ICMD_IF_DCMPG_GE:     /* {ALL} */
450 case ICMD_IF_DCMPG_GT:     /* {ALL} */
451 case ICMD_IF_DCMPG_LE:     /* {ALL} */
452         /* {RESULTNOW} */
453         TYPECHECK_COUNT(stat_ins_branch);
454
455         /* propagate stack and variables to the target block */
456         REACH(IPTR->dst);
457         break;
458
459         /****************************************/
460         /* SWITCHES                             */
461
462 case ICMD_TABLESWITCH:     /* {ALL} */
463         /* {RESULTNOW} */
464         TYPECHECK_COUNT(stat_ins_switch);
465
466         table = IPTR->dst.table;
467         i = IPTR->sx.s23.s3.tablehigh
468         - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
469
470         while (--i >= 0) {
471                 REACH(*table);
472                 table++;
473         }
474
475         LOG("switch done");
476         break;
477
478 case ICMD_LOOKUPSWITCH:    /* {ALL} */
479         /* {RESULTNOW} */
480         TYPECHECK_COUNT(stat_ins_switch);
481
482         lookup = IPTR->dst.lookup;
483         i = IPTR->sx.s23.s2.lookupcount;
484         REACH(IPTR->sx.s23.s3.lookupdefault);
485
486         while (--i >= 0) {
487                 REACH(lookup->target);
488                 lookup++;
489         }
490
491         LOG("switch done");
492         break;
493
494
495         /****************************************/
496         /* ADDRESS RETURNS AND THROW            */
497
498 case ICMD_ATHROW:
499         TYPECHECK_COUNT(stat_ins_athrow);
500         r = typeinfo_is_assignable_to_class(&OP1->typeinfo,
501                         CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
502         if (r == typecheck_FALSE)
503                 VERIFY_ERROR("illegal instruction: ATHROW on non-Throwable");
504         if (r == typecheck_FAIL)
505                 EXCEPTION;
506         if (r == typecheck_MAYBE) {
507                 /* the check has to be postponed. we need a patcher */
508                 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
509                 IPTR->sx.s23.s2.uc = create_unresolved_class(
510                                 METHOD,
511                                 /* XXX make this more efficient, use class_java_lang_Throwable
512                                  * directly */
513                                 class_get_classref(METHOD->class,utf_java_lang_Throwable),
514                                 &OP1->typeinfo);
515                 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
516         }
517         break;
518
519 case ICMD_ARETURN:
520         TYPECHECK_COUNT(stat_ins_areturn);
521         if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
522                 VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
523
524         if (STATE->returntype.type != TYPE_ADR
525                         || (r = typeinfo_is_assignable(&OP1->typeinfo,&(STATE->returntype.typeinfo)))
526                         == typecheck_FALSE)
527                 VERIFY_ERROR("Return type mismatch");
528         if (r == typecheck_FAIL)
529                 EXCEPTION;
530         if (r == typecheck_MAYBE) {
531                 /* the check has to be postponed, we need a patcher */
532                 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
533                 IPTR->sx.s23.s2.uc = create_unresolved_class(
534                                 METHOD,
535                                 METHOD->parseddesc->returntype.classref,
536                                 &OP1->typeinfo);
537                 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
538         }
539         goto return_tail;
540
541         /****************************************/
542         /* PRIMITIVE RETURNS                    */
543
544 case ICMD_IRETURN:
545         if (STATE->returntype.type != TYPE_INT)
546                 VERIFY_ERROR("Return type mismatch");
547         goto return_tail;
548
549 case ICMD_LRETURN:
550         if (STATE->returntype.type != TYPE_LNG)
551                 VERIFY_ERROR("Return type mismatch");
552         goto return_tail;
553
554 case ICMD_FRETURN:
555         if (STATE->returntype.type != TYPE_FLT)
556                 VERIFY_ERROR("Return type mismatch");
557         goto return_tail;
558
559 case ICMD_DRETURN:
560         if (STATE->returntype.type != TYPE_DBL)
561                 VERIFY_ERROR("Return type mismatch");
562         goto return_tail;
563
564 case ICMD_RETURN:
565         if (STATE->returntype.type != TYPE_VOID)
566                 VERIFY_ERROR("Return type mismatch");
567
568 return_tail:
569         TYPECHECK_COUNT(stat_ins_primitive_return);
570
571         if (STATE->initmethod && METHOD->class != class_java_lang_Object) {
572                 /* Check if the 'this' instance has been initialized. */
573                 LOG("Checking <init> marker");
574 #if defined(TYPECHECK_VARIABLESBASED)
575                 if (!typevector_checktype(jd->var,STATE->numlocals-1,TYPE_INT))
576 #else
577                 if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
578 #endif
579                         VERIFY_ERROR("<init> method does not initialize 'this'");
580         }
581         break;
582
583         /****************************************/
584         /* SUBROUTINE INSTRUCTIONS              */
585
586 case ICMD_JSR: /* {VARIABLESBASED,TYPEINFERER} */
587         TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
588         REACH(IPTR->sx.s23.s3.jsrtarget);
589         break;
590
591 case ICMD_JSR: /* {STACKBASED} */
592         /* {RESULTNOW} */
593         tbptr = BLOCK_OF(IPTR->sx.s23.s3.jsrtarget.insindex);
594
595         TYPEINFO_INIT_RETURNADDRESS(stack[0].typeinfo, tbptr);
596         REACH_BLOCK(tbptr);
597
598         stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
599         if (stack == NULL)
600                 EXCEPTION;
601         break;
602
603 case ICMD_RET: /* {VARIABLESBASED,TYPEINFERER} */
604 #if !defined(TYPECHECK_TYPEINFERER)
605         /* check returnAddress variable */
606         if (!typevector_checkretaddr(jd->var,IPTR->s1.varindex))
607                 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
608 #endif
609         REACH(IPTR->dst);
610         break;
611
612 case ICMD_RET: /* {STACKBASED} */
613         /* {RESULTNOW} */
614         CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_RET);
615         if (!TYPEINFO_IS_PRIMITIVE(STATE->locals[IPTR->s1.varindex].typeinfo))
616                 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
617
618         if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
619                 EXCEPTION;
620         break;
621
622         /****************************************/
623         /* INVOKATIONS                          */
624
625 case ICMD_INVOKEVIRTUAL:   /* {VARIABLESBASED,TYPEINFERER} */
626 case ICMD_INVOKESPECIAL:   /* {VARIABLESBASED,TYPEINFERER} */
627 case ICMD_INVOKESTATIC:    /* {VARIABLESBASED,TYPEINFERER} */
628 case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED,TYPEINFERER} */
629         TYPECHECK_COUNT(stat_ins_invoke);
630         if (!handle_invocation(state))
631                 EXCEPTION;
632         TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
633         break;
634
635 case ICMD_INVOKEVIRTUAL:   /* {STACKBASED} */
636 case ICMD_INVOKESPECIAL:   /* {STACKBASED} */
637 case ICMD_INVOKESTATIC:    /* {STACKBASED} */
638 case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
639         TYPECHECK_COUNT(stat_ins_invoke);
640
641         INSTRUCTION_GET_METHODDESC(IPTR, md);
642         CHECK_STACK_DEPTH(md->paramslots);
643
644         if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
645                 EXCEPTION;
646
647         stack -= md->paramslots;
648
649         if (md->returntype.type != TYPE_VOID) {
650                 if (IS_2_WORD_TYPE(md->returntype.type)) {
651                         CHECK_STACK_SPACE(2);
652                         stack += 2;
653                         stack[0].type = TYPE_VOID;
654                         stack[-1].type = md->returntype.type;
655                 }
656                 else {
657                         CHECK_STACK_SPACE(1);
658                         stack += 1;
659                         stack[0].type = md->returntype.type;
660                 }
661         }
662         TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
663         break;
664
665         /****************************************/
666         /* MULTIANEWARRAY                       */
667
668 case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED,TYPEINFERER} */
669         if (!handle_multianewarray(STATE))
670                 EXCEPTION;
671         break;
672
673 case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
674         if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
675                 EXCEPTION;
676         stack -= (IPTR->s1.argcount - 1);
677         stack[0].type = TYPE_ADR;
678         break;
679
680         /****************************************/
681         /* BUILTINS                             */
682
683 case ICMD_BUILTIN: /* {VARIABLESBASED,TYPEINFERER} */
684         TYPECHECK_COUNT(stat_ins_builtin);
685         if (!handle_builtin(state))
686                 EXCEPTION;
687         break;
688
689 case ICMD_BUILTIN: /* {STACKBASED} */
690         TYPECHECK_COUNT(stat_ins_builtin);
691         if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
692                 EXCEPTION;
693
694         /* pop operands and push return value */
695         {
696                 u1 rtype = IPTR->sx.s23.s3.bte->md->returntype.type;
697                 stack -=  IPTR->sx.s23.s3.bte->md->paramslots;
698                 if (rtype != TYPE_VOID) {
699                         if (IS_2_WORD_TYPE(rtype))
700                                 stack += 2;
701                         else
702                                 stack += 1;
703                 }
704         }
705         break;
706
707 /* the following code is only used by the stackbased verifier */
708
709 case ICMD_POP: /* {STACKBASED} */
710         /* we pop 1 */
711         CHECK_CAT1(stack[0]);
712         break;
713
714 case ICMD_POP2: /* {STACKBASED} */
715         /* we pop either 11 or 2 */
716         if (IS_CAT1(stack[0]))
717                 CHECK_CAT1(stack[-1]);
718         break;
719
720 case ICMD_SWAP: /* {STACKBASED} */
721         CHECK_CAT1(stack[0]);
722         CHECK_CAT1(stack[-1]);
723
724         COPY_SLOT(stack[ 0], temp     );
725         COPY_SLOT(stack[-1], stack[ 0]);
726         COPY_SLOT(temp     , stack[-1]);
727         break;
728
729 case ICMD_DUP: /* {STACKBASED} */
730         /* we dup 1 */
731         CHECK_CAT1(stack[0]);
732
733         COPY_SLOT(stack[ 0], stack[ 1]);
734         break;
735
736 case ICMD_DUP_X1: /* {STACKBASED} */
737         /* we dup 1 */
738         CHECK_CAT1(stack[0]);
739         /* we skip 1 */
740         CHECK_CAT1(stack[-1]);
741
742         COPY_SLOT(stack[ 0], stack[ 1]);
743         COPY_SLOT(stack[-1], stack[ 0]);
744         COPY_SLOT(stack[ 1], stack[-1]);
745         break;
746
747 case ICMD_DUP_X2: /* {STACKBASED} */
748         /* we dup 1 */
749         CHECK_CAT1(stack[0]);
750         /* we skip either 11 or 2 */
751         if (IS_CAT1(stack[-1]))
752                 CHECK_CAT1(stack[-2]);
753
754         COPY_SLOT(stack[ 0], stack[ 1]);
755         COPY_SLOT(stack[-1], stack[ 0]);
756         COPY_SLOT(stack[-2], stack[-1]);
757         COPY_SLOT(stack[ 1], stack[-2]);
758         break;
759
760 case ICMD_DUP2: /* {STACKBASED} */
761         /* we dup either 11 or 2 */
762         if (IS_CAT1(stack[0]))
763                 CHECK_CAT1(stack[-1]);
764
765         COPY_SLOT(stack[ 0], stack[ 2]);
766         COPY_SLOT(stack[-1], stack[ 1]);
767         break;
768
769 case ICMD_DUP2_X1: /* {STACKBASED} */
770         /* we dup either 11 or 2 */
771         if (IS_CAT1(stack[0]))
772                 CHECK_CAT1(stack[-1]);
773         /* we skip 1 */
774         CHECK_CAT1(stack[-2]);
775
776         COPY_SLOT(stack[ 0], stack[ 2]);
777         COPY_SLOT(stack[-1], stack[ 1]);
778         COPY_SLOT(stack[-2], stack[ 0]);
779         COPY_SLOT(stack[ 2], stack[-1]);
780         COPY_SLOT(stack[ 1], stack[-2]);
781         break;
782
783 case ICMD_DUP2_X2: /* {STACKBASED} */
784         /* we dup either 11 or 2 */
785         if (IS_CAT1(stack[0]))
786                 CHECK_CAT1(stack[-1]);
787         /* we skip either 11 or 2 */
788         if (IS_CAT1(stack[-2]))
789                 CHECK_CAT1(stack[-3]);
790
791         COPY_SLOT(stack[ 0], stack[ 2]);
792         COPY_SLOT(stack[-1], stack[ 1]);
793         COPY_SLOT(stack[-2], stack[ 0]);
794         COPY_SLOT(stack[-3], stack[-1]);
795         COPY_SLOT(stack[ 2], stack[-2]);
796         COPY_SLOT(stack[ 1], stack[-3]);
797         break;
798
799
800 /* this marker is needed by generate.pl: */
801 /* {END_OF_CODE} */
802
803 /*
804  * These are local overrides for various environment variables in Emacs.
805  * Please do not remove this and leave it at the end of the file, where
806  * Emacs will automagically detect them.
807  * ---------------------------------------------------------------------
808  * Local variables:
809  * mode: c
810  * indent-tabs-mode: t
811  * c-basic-offset: 4
812  * tab-width: 4
813  * End:
814  * vim:noexpandtab:sw=4:ts=4:
815  */