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