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