1 /* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
35 #if 0 /* (needed for code examples in the following comment) */
36 /******************************************************************************/
37 /* This file contains ICMD-specific code for type checking and type
38 * inference. It is an input file for the verifier generator
39 * (src/vm/jit/verify/generate.pl). The verifier generator creates
40 * code for three compiler passes:
41 * - stack-based type-infering verification
42 * - vasiables-based type-infering verification
43 * - type inference pass (no verification - used for optimizing compiler)
45 * The rest of this file must consist of "case" clauses starting in
46 * the first column. Each clause can be marked with tags like this:
48 */ case ICMD_CONSTANT: /* {TAG, TAG, ...} */
50 * This must be on one line. The following tags are defined:
51 * STACKBASED..........use this clause for the stack-based verifier
52 * VARIABLESBASED......use this clause for the variables-based verifier
53 * TYPEINFERER.........use this clause for the type inference pass
54 * ALL.................use for all passes
56 * If no tag is specified, {STACKBASED,VARIABLESBASED} is assumed.
58 * There are also tags that can be used inside a clause like this:
62 * The following tags are defined within clauses:
63 * RESULTNOW...........generate code for modelling the stack action
64 * _before_ the user-defined code in the clause
65 * (Default is to model the stack action afterwards.)
67 * The following macros are pre-defined:
69 * TYPECHECK_STACKBASED.......iff compiling the stack-based verifier
70 * TYPECHECK_VARIABLESBASED...iff compiling the variables-based verifier
71 * TYPECHECK_TYPEINFERER......iff compiling the type inference pass
73 /******************************************************************************/
74 #endif /* (end #if 0) */
77 /* this marker is needed by generate.pl: */
80 /****************************************/
83 /* We just need to copy the typeinfo */
84 /* for slots containing addresses. */
86 /* (These are only used by the variables based verifier.) */
88 case ICMD_MOVE: /* {VARIABLESBASED,TYPEINFERER} */
89 case ICMD_COPY: /* {VARIABLESBASED,TYPEINFERER} */
90 TYPECHECK_COUNT(stat_ins_stack);
91 COPYTYPE(IPTR->s1, IPTR->dst);
92 DST->type = OP1->type;
95 /****************************************/
96 /* LOADING ADDRESS FROM VARIABLE */
98 case ICMD_ALOAD: /* {ALL} */
99 TYPECHECK_COUNT(stat_ins_aload);
101 #if !defined(TYPECHECK_TYPEINFERER)
102 /* loading a returnAddress is not allowed */
103 if (!TYPEDESC_IS_REFERENCE(*OP1)) {
104 VERIFY_ERROR("illegal instruction: ALOAD loading non-reference");
107 TYPEINFO_COPY(OP1->typeinfo,DST->typeinfo);
110 /****************************************/
111 /* STORING ADDRESS TO VARIABLE */
113 case ICMD_ASTORE: /* {ALL} */
114 TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
117 /****************************************/
118 /* LOADING ADDRESS FROM ARRAY */
120 case ICMD_AALOAD: /* {ALL} */
121 #if !defined(TYPECHECK_TYPEINFERER)
122 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
123 VERIFY_ERROR("illegal instruction: AALOAD on non-reference array");
126 if (!typeinfo_init_component(&OP1->typeinfo,&DST->typeinfo))
130 /****************************************/
133 case ICMD_PUTFIELD: /* {STACKBASED} */
134 CHECK_STACK_DEPTH(2);
135 if (!IS_CAT1(stack[0])) {
136 CHECK_STACK_DEPTH(3);
139 CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
140 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
145 case ICMD_PUTSTATIC: /* {STACKBASED} */
146 CHECK_STACK_DEPTH(1);
147 if (!IS_CAT1(stack[0])) {
148 /* (stack depth >= 2 is guaranteed) */
151 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
156 case ICMD_GETFIELD: /* {STACKBASED} */
157 CHECK_STACK_TYPE(stack[0], TYPE_ADR);
158 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
163 case ICMD_GETSTATIC: /* {STACKBASED} */
164 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
169 case ICMD_PUTFIELD: /* {VARIABLESBASED} */
170 if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
175 case ICMD_PUTSTATIC: /* {VARIABLESBASED} */
176 if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
181 case ICMD_PUTFIELDCONST: /* {VARIABLESBASED} */
182 /* XXX this mess will go away with const operands */
183 INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
184 constvalue.type = fieldref->parseddesc.fd->type;
185 if (IS_ADR_TYPE(constvalue.type)) {
186 if (state->iptr->sx.val.anyptr) {
187 classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
188 ? class_java_lang_Class : class_java_lang_String;
190 assert(cc->state & CLASS_LINKED);
191 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
194 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
197 if (!handle_fieldaccess(state, VAROP(iptr->s1), &constvalue))
202 case ICMD_PUTSTATICCONST: /* {VARIABLESBASED} */
203 /* XXX this mess will go away with const operands */
204 INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
205 constvalue.type = fieldref->parseddesc.fd->type;
206 if (IS_ADR_TYPE(constvalue.type)) {
207 if (state->iptr->sx.val.anyptr) {
208 classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
209 ? class_java_lang_Class : class_java_lang_String;
211 assert(cc->state & CLASS_LINKED);
212 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
215 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
218 if (!handle_fieldaccess(state, NULL, &constvalue))
223 case ICMD_GETFIELD: /* {VARIABLESBASED,TYPEINFERER} */
224 if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
229 case ICMD_GETSTATIC: /* {VARIABLESBASED,TYPEINFERER} */
230 if (!handle_fieldaccess(state, NULL, NULL))
235 /****************************************/
236 /* PRIMITIVE ARRAY ACCESS */
238 case ICMD_ARRAYLENGTH:
239 if (!TYPEINFO_MAYBE_ARRAY(OP1->typeinfo)
240 && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
241 VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
245 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
246 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
247 VERIFY_ERROR("Array type mismatch");
251 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
252 VERIFY_ERROR("Array type mismatch");
256 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
257 VERIFY_ERROR("Array type mismatch");
261 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
262 VERIFY_ERROR("Array type mismatch");
266 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
267 VERIFY_ERROR("Array type mismatch");
271 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
272 VERIFY_ERROR("Array type mismatch");
276 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
277 VERIFY_ERROR("Array type mismatch");
281 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
282 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
283 VERIFY_ERROR("Array type mismatch");
287 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
288 VERIFY_ERROR("Array type mismatch");
292 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
293 VERIFY_ERROR("Array type mismatch");
297 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
298 VERIFY_ERROR("Array type mismatch");
302 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
303 VERIFY_ERROR("Array type mismatch");
307 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
308 VERIFY_ERROR("Array type mismatch");
312 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
313 VERIFY_ERROR("Array type mismatch");
317 /* we just check the basic input types and that the */
318 /* destination is an array of references. Assignability to */
319 /* the actual array must be checked at runtime, each time the */
320 /* instruction is performed. (See builtin_canstore.) */
321 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
322 VERIFY_ERROR("illegal instruction: AASTORE to non-reference array");
325 case ICMD_IASTORECONST:
326 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_INT))
327 VERIFY_ERROR("Array type mismatch");
330 case ICMD_LASTORECONST:
331 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_LONG))
332 VERIFY_ERROR("Array type mismatch");
335 case ICMD_BASTORECONST:
336 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BOOLEAN)
337 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BYTE))
338 VERIFY_ERROR("Array type mismatch");
341 case ICMD_CASTORECONST:
342 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_CHAR))
343 VERIFY_ERROR("Array type mismatch");
346 case ICMD_SASTORECONST:
347 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_SHORT))
348 VERIFY_ERROR("Array type mismatch");
351 /****************************************/
352 /* ADDRESS CONSTANTS */
354 case ICMD_ACONST: /* {ALL} */
355 if (IPTR->flags.bits & INS_FLAG_CLASS) {
356 /* a java.lang.Class reference */
357 TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
360 if (IPTR->sx.val.anyptr == NULL)
361 TYPEINFO_INIT_NULLTYPE(DST->typeinfo);
363 /* string constant (or constant for builtin function) */
364 typeinfo_init_classinfo(&(DST->typeinfo),class_java_lang_String);
369 /****************************************/
370 /* CHECKCAST AND INSTANCEOF */
372 case ICMD_CHECKCAST: /* {ALL} */
373 #if !defined(TYPECHECK_TYPEINFERER)
374 /* returnAddress is not allowed */
375 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
376 VERIFY_ERROR("Illegal instruction: CHECKCAST on non-reference");
379 /* XXX only if narrower */
380 if (!typeinfo_init_class(&(DST->typeinfo),IPTR->sx.s23.s3.c))
384 case ICMD_INSTANCEOF:
385 /* returnAddress is not allowed */
386 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
387 VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
389 /* XXX should propagate type information to the following if-branches */
392 /****************************************/
393 /* BRANCH INSTRUCTIONS */
395 case ICMD_GOTO: /* {ALL} */
396 case ICMD_IFNULL: /* {ALL} */
397 case ICMD_IFNONNULL: /* {ALL} */
398 case ICMD_IFEQ: /* {ALL} */
399 case ICMD_IFNE: /* {ALL} */
400 case ICMD_IFLT: /* {ALL} */
401 case ICMD_IFGE: /* {ALL} */
402 case ICMD_IFGT: /* {ALL} */
403 case ICMD_IFLE: /* {ALL} */
404 case ICMD_IF_ICMPEQ: /* {ALL} */
405 case ICMD_IF_ICMPNE: /* {ALL} */
406 case ICMD_IF_ICMPLT: /* {ALL} */
407 case ICMD_IF_ICMPGE: /* {ALL} */
408 case ICMD_IF_ICMPGT: /* {ALL} */
409 case ICMD_IF_ICMPLE: /* {ALL} */
410 case ICMD_IF_ACMPEQ: /* {ALL} */
411 case ICMD_IF_ACMPNE: /* {ALL} */
413 case ICMD_IF_LEQ: /* {ALL} */
414 case ICMD_IF_LNE: /* {ALL} */
415 case ICMD_IF_LLT: /* {ALL} */
416 case ICMD_IF_LGE: /* {ALL} */
417 case ICMD_IF_LGT: /* {ALL} */
418 case ICMD_IF_LLE: /* {ALL} */
420 case ICMD_IF_LCMPEQ: /* {ALL} */
421 case ICMD_IF_LCMPNE: /* {ALL} */
422 case ICMD_IF_LCMPLT: /* {ALL} */
423 case ICMD_IF_LCMPGE: /* {ALL} */
424 case ICMD_IF_LCMPGT: /* {ALL} */
425 case ICMD_IF_LCMPLE: /* {ALL} */
427 case ICMD_IF_FCMPEQ: /* {ALL} */
428 case ICMD_IF_FCMPNE: /* {ALL} */
430 case ICMD_IF_FCMPL_LT: /* {ALL} */
431 case ICMD_IF_FCMPL_GE: /* {ALL} */
432 case ICMD_IF_FCMPL_GT: /* {ALL} */
433 case ICMD_IF_FCMPL_LE: /* {ALL} */
435 case ICMD_IF_FCMPG_LT: /* {ALL} */
436 case ICMD_IF_FCMPG_GE: /* {ALL} */
437 case ICMD_IF_FCMPG_GT: /* {ALL} */
438 case ICMD_IF_FCMPG_LE: /* {ALL} */
440 case ICMD_IF_DCMPEQ: /* {ALL} */
441 case ICMD_IF_DCMPNE: /* {ALL} */
443 case ICMD_IF_DCMPL_LT: /* {ALL} */
444 case ICMD_IF_DCMPL_GE: /* {ALL} */
445 case ICMD_IF_DCMPL_GT: /* {ALL} */
446 case ICMD_IF_DCMPL_LE: /* {ALL} */
448 case ICMD_IF_DCMPG_LT: /* {ALL} */
449 case ICMD_IF_DCMPG_GE: /* {ALL} */
450 case ICMD_IF_DCMPG_GT: /* {ALL} */
451 case ICMD_IF_DCMPG_LE: /* {ALL} */
453 TYPECHECK_COUNT(stat_ins_branch);
455 /* propagate stack and variables to the target block */
459 /****************************************/
462 case ICMD_TABLESWITCH: /* {ALL} */
464 TYPECHECK_COUNT(stat_ins_switch);
466 table = IPTR->dst.table;
467 i = IPTR->sx.s23.s3.tablehigh
468 - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
478 case ICMD_LOOKUPSWITCH: /* {ALL} */
480 TYPECHECK_COUNT(stat_ins_switch);
482 lookup = IPTR->dst.lookup;
483 i = IPTR->sx.s23.s2.lookupcount;
484 REACH(IPTR->sx.s23.s3.lookupdefault);
487 REACH(lookup->target);
495 /****************************************/
496 /* ADDRESS RETURNS AND THROW */
499 TYPECHECK_COUNT(stat_ins_athrow);
500 r = typeinfo_is_assignable_to_class(&OP1->typeinfo,
501 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
502 if (r == typecheck_FALSE)
503 VERIFY_ERROR("illegal instruction: ATHROW on non-Throwable");
504 if (r == typecheck_FAIL)
506 if (r == typecheck_MAYBE) {
507 /* the check has to be postponed. we need a patcher */
508 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
509 IPTR->sx.s23.s2.uc = create_unresolved_class(
511 /* XXX make this more efficient, use class_java_lang_Throwable
513 class_get_classref(METHOD->class,utf_java_lang_Throwable),
515 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
520 TYPECHECK_COUNT(stat_ins_areturn);
521 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
522 VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
524 if (STATE->returntype.type != TYPE_ADR
525 || (r = typeinfo_is_assignable(&OP1->typeinfo,&(STATE->returntype.typeinfo)))
527 VERIFY_ERROR("Return type mismatch");
528 if (r == typecheck_FAIL)
530 if (r == typecheck_MAYBE) {
531 /* the check has to be postponed, we need a patcher */
532 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
533 IPTR->sx.s23.s2.uc = create_unresolved_class(
535 METHOD->parseddesc->returntype.classref,
537 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
541 /****************************************/
542 /* PRIMITIVE RETURNS */
545 if (STATE->returntype.type != TYPE_INT)
546 VERIFY_ERROR("Return type mismatch");
550 if (STATE->returntype.type != TYPE_LNG)
551 VERIFY_ERROR("Return type mismatch");
555 if (STATE->returntype.type != TYPE_FLT)
556 VERIFY_ERROR("Return type mismatch");
560 if (STATE->returntype.type != TYPE_DBL)
561 VERIFY_ERROR("Return type mismatch");
565 if (STATE->returntype.type != TYPE_VOID)
566 VERIFY_ERROR("Return type mismatch");
569 TYPECHECK_COUNT(stat_ins_primitive_return);
571 if (STATE->initmethod && METHOD->class != class_java_lang_Object) {
572 /* Check if the 'this' instance has been initialized. */
573 LOG("Checking <init> marker");
574 #if defined(TYPECHECK_VARIABLESBASED)
575 if (!typevector_checktype(jd->var,STATE->numlocals-1,TYPE_INT))
577 if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
579 VERIFY_ERROR("<init> method does not initialize 'this'");
583 /****************************************/
584 /* SUBROUTINE INSTRUCTIONS */
586 case ICMD_JSR: /* {VARIABLESBASED,TYPEINFERER} */
587 TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
588 REACH(IPTR->sx.s23.s3.jsrtarget);
591 case ICMD_JSR: /* {STACKBASED} */
593 tbptr = BLOCK_OF(IPTR->sx.s23.s3.jsrtarget.insindex);
595 TYPEINFO_INIT_RETURNADDRESS(stack[0].typeinfo, tbptr);
598 stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
603 case ICMD_RET: /* {VARIABLESBASED,TYPEINFERER} */
604 #if !defined(TYPECHECK_TYPEINFERER)
605 /* check returnAddress variable */
606 if (!typevector_checkretaddr(jd->var,IPTR->s1.varindex))
607 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
612 case ICMD_RET: /* {STACKBASED} */
614 CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_RET);
615 if (!TYPEINFO_IS_PRIMITIVE(STATE->locals[IPTR->s1.varindex].typeinfo))
616 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
618 if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
622 /****************************************/
625 case ICMD_INVOKEVIRTUAL: /* {VARIABLESBASED,TYPEINFERER} */
626 case ICMD_INVOKESPECIAL: /* {VARIABLESBASED,TYPEINFERER} */
627 case ICMD_INVOKESTATIC: /* {VARIABLESBASED,TYPEINFERER} */
628 case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED,TYPEINFERER} */
629 TYPECHECK_COUNT(stat_ins_invoke);
630 if (!handle_invocation(state))
632 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
635 case ICMD_INVOKEVIRTUAL: /* {STACKBASED} */
636 case ICMD_INVOKESPECIAL: /* {STACKBASED} */
637 case ICMD_INVOKESTATIC: /* {STACKBASED} */
638 case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
639 TYPECHECK_COUNT(stat_ins_invoke);
641 INSTRUCTION_GET_METHODDESC(IPTR, md);
642 CHECK_STACK_DEPTH(md->paramslots);
644 if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
647 stack -= md->paramslots;
649 if (md->returntype.type != TYPE_VOID) {
650 if (IS_2_WORD_TYPE(md->returntype.type)) {
651 CHECK_STACK_SPACE(2);
653 stack[0].type = TYPE_VOID;
654 stack[-1].type = md->returntype.type;
657 CHECK_STACK_SPACE(1);
659 stack[0].type = md->returntype.type;
662 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
665 /****************************************/
668 case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED,TYPEINFERER} */
669 if (!handle_multianewarray(STATE))
673 case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
674 if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
676 stack -= (IPTR->s1.argcount - 1);
677 stack[0].type = TYPE_ADR;
680 /****************************************/
683 case ICMD_BUILTIN: /* {VARIABLESBASED,TYPEINFERER} */
684 TYPECHECK_COUNT(stat_ins_builtin);
685 if (!handle_builtin(state))
689 case ICMD_BUILTIN: /* {STACKBASED} */
690 TYPECHECK_COUNT(stat_ins_builtin);
691 if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
694 /* pop operands and push return value */
696 u1 rtype = IPTR->sx.s23.s3.bte->md->returntype.type;
697 stack -= IPTR->sx.s23.s3.bte->md->paramslots;
698 if (rtype != TYPE_VOID) {
699 if (IS_2_WORD_TYPE(rtype))
707 /* the following code is only used by the stackbased verifier */
709 case ICMD_POP: /* {STACKBASED} */
711 CHECK_CAT1(stack[0]);
714 case ICMD_POP2: /* {STACKBASED} */
715 /* we pop either 11 or 2 */
716 if (IS_CAT1(stack[0]))
717 CHECK_CAT1(stack[-1]);
720 case ICMD_SWAP: /* {STACKBASED} */
721 CHECK_CAT1(stack[0]);
722 CHECK_CAT1(stack[-1]);
724 COPY_SLOT(stack[ 0], temp );
725 COPY_SLOT(stack[-1], stack[ 0]);
726 COPY_SLOT(temp , stack[-1]);
729 case ICMD_DUP: /* {STACKBASED} */
731 CHECK_CAT1(stack[0]);
733 COPY_SLOT(stack[ 0], stack[ 1]);
736 case ICMD_DUP_X1: /* {STACKBASED} */
738 CHECK_CAT1(stack[0]);
740 CHECK_CAT1(stack[-1]);
742 COPY_SLOT(stack[ 0], stack[ 1]);
743 COPY_SLOT(stack[-1], stack[ 0]);
744 COPY_SLOT(stack[ 1], stack[-1]);
747 case ICMD_DUP_X2: /* {STACKBASED} */
749 CHECK_CAT1(stack[0]);
750 /* we skip either 11 or 2 */
751 if (IS_CAT1(stack[-1]))
752 CHECK_CAT1(stack[-2]);
754 COPY_SLOT(stack[ 0], stack[ 1]);
755 COPY_SLOT(stack[-1], stack[ 0]);
756 COPY_SLOT(stack[-2], stack[-1]);
757 COPY_SLOT(stack[ 1], stack[-2]);
760 case ICMD_DUP2: /* {STACKBASED} */
761 /* we dup either 11 or 2 */
762 if (IS_CAT1(stack[0]))
763 CHECK_CAT1(stack[-1]);
765 COPY_SLOT(stack[ 0], stack[ 2]);
766 COPY_SLOT(stack[-1], stack[ 1]);
769 case ICMD_DUP2_X1: /* {STACKBASED} */
770 /* we dup either 11 or 2 */
771 if (IS_CAT1(stack[0]))
772 CHECK_CAT1(stack[-1]);
774 CHECK_CAT1(stack[-2]);
776 COPY_SLOT(stack[ 0], stack[ 2]);
777 COPY_SLOT(stack[-1], stack[ 1]);
778 COPY_SLOT(stack[-2], stack[ 0]);
779 COPY_SLOT(stack[ 2], stack[-1]);
780 COPY_SLOT(stack[ 1], stack[-2]);
783 case ICMD_DUP2_X2: /* {STACKBASED} */
784 /* we dup either 11 or 2 */
785 if (IS_CAT1(stack[0]))
786 CHECK_CAT1(stack[-1]);
787 /* we skip either 11 or 2 */
788 if (IS_CAT1(stack[-2]))
789 CHECK_CAT1(stack[-3]);
791 COPY_SLOT(stack[ 0], stack[ 2]);
792 COPY_SLOT(stack[-1], stack[ 1]);
793 COPY_SLOT(stack[-2], stack[ 0]);
794 COPY_SLOT(stack[-3], stack[-1]);
795 COPY_SLOT(stack[ 2], stack[-2]);
796 COPY_SLOT(stack[ 1], stack[-3]);
800 /* this marker is needed by generate.pl: */
804 * These are local overrides for various environment variables in Emacs.
805 * Please do not remove this and leave it at the end of the file, where
806 * Emacs will automagically detect them.
807 * ---------------------------------------------------------------------
810 * indent-tabs-mode: t
814 * vim:noexpandtab:sw=4:ts=4: