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