1 /* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
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
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
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)
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:
40 */ case ICMD_CONSTANT: /* {TAG, TAG, ...} */
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
48 * If no tag is specified, {STACKBASED,VARIABLESBASED} is assumed.
50 * There are also tags that can be used inside a clause like this:
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.)
59 * The following macros are pre-defined:
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
65 /******************************************************************************/
66 #endif /* (end #if 0) */
69 /* this marker is needed by generate.pl: */
72 /****************************************/
75 /* We just need to copy the typeinfo */
76 /* for slots containing addresses. */
78 /* (These are only used by the variables based verifier.) */
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;
87 /****************************************/
88 /* LOADING ADDRESS FROM VARIABLE */
90 case ICMD_ALOAD: /* {ALL} */
91 TYPECHECK_COUNT(stat_ins_aload);
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");
99 TYPEINFO_COPY(OP1->typeinfo,DST->typeinfo);
102 /****************************************/
103 /* STORING ADDRESS TO VARIABLE */
105 case ICMD_ASTORE: /* {ALL} */
106 TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
109 /****************************************/
110 /* LOADING ADDRESS FROM ARRAY */
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");
118 if (!typeinfo_init_component(&OP1->typeinfo,&DST->typeinfo))
122 /****************************************/
125 case ICMD_PUTFIELD: /* {STACKBASED} */
126 CHECK_STACK_DEPTH(2);
127 if (!IS_CAT1(stack[0])) {
128 CHECK_STACK_DEPTH(3);
131 CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
132 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
137 case ICMD_PUTSTATIC: /* {STACKBASED} */
138 CHECK_STACK_DEPTH(1);
139 if (!IS_CAT1(stack[0])) {
140 /* (stack depth >= 2 is guaranteed) */
143 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
148 case ICMD_GETFIELD: /* {STACKBASED} */
149 CHECK_STACK_TYPE(stack[0], TYPE_ADR);
150 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
155 case ICMD_GETSTATIC: /* {STACKBASED} */
156 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
161 case ICMD_PUTFIELD: /* {VARIABLESBASED} */
162 if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
167 case ICMD_PUTSTATIC: /* {VARIABLESBASED} */
168 if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
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;
182 assert(cc->state & CLASS_LINKED);
183 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
186 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
189 if (!handle_fieldaccess(state, VAROP(iptr->s1), &constvalue))
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;
203 assert(cc->state & CLASS_LINKED);
204 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
207 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
210 if (!handle_fieldaccess(state, NULL, &constvalue))
215 case ICMD_GETFIELD: /* {VARIABLESBASED,TYPEINFERER} */
216 if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
221 case ICMD_GETSTATIC: /* {VARIABLESBASED,TYPEINFERER} */
222 if (!handle_fieldaccess(state, NULL, NULL))
227 /****************************************/
228 /* PRIMITIVE ARRAY ACCESS */
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");
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");
243 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
244 VERIFY_ERROR("Array type mismatch");
248 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
249 VERIFY_ERROR("Array type mismatch");
253 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
254 VERIFY_ERROR("Array type mismatch");
258 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
259 VERIFY_ERROR("Array type mismatch");
263 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
264 VERIFY_ERROR("Array type mismatch");
268 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
269 VERIFY_ERROR("Array type mismatch");
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");
279 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
280 VERIFY_ERROR("Array type mismatch");
284 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
285 VERIFY_ERROR("Array type mismatch");
289 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
290 VERIFY_ERROR("Array type mismatch");
294 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
295 VERIFY_ERROR("Array type mismatch");
299 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
300 VERIFY_ERROR("Array type mismatch");
304 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
305 VERIFY_ERROR("Array type mismatch");
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");
317 case ICMD_IASTORECONST:
318 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_INT))
319 VERIFY_ERROR("Array type mismatch");
322 case ICMD_LASTORECONST:
323 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_LONG))
324 VERIFY_ERROR("Array type mismatch");
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");
333 case ICMD_CASTORECONST:
334 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_CHAR))
335 VERIFY_ERROR("Array type mismatch");
338 case ICMD_SASTORECONST:
339 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_SHORT))
340 VERIFY_ERROR("Array type mismatch");
343 /****************************************/
344 /* ADDRESS CONSTANTS */
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);
352 if (IPTR->sx.val.anyptr == NULL)
353 TYPEINFO_INIT_NULLTYPE(DST->typeinfo);
355 /* string constant (or constant for builtin function) */
356 typeinfo_init_classinfo(&(DST->typeinfo),class_java_lang_String);
361 /****************************************/
362 /* CHECKCAST AND INSTANCEOF */
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");
371 /* XXX only if narrower */
372 if (!typeinfo_init_class(&(DST->typeinfo),IPTR->sx.s23.s3.c))
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");
381 /* XXX should propagate type information to the following if-branches */
384 /****************************************/
385 /* BRANCH INSTRUCTIONS */
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} */
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} */
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} */
419 TYPECHECK_COUNT(stat_ins_branch);
421 /* propagate stack and variables to the target block */
425 /****************************************/
428 case ICMD_TABLESWITCH: /* {ALL} */
430 TYPECHECK_COUNT(stat_ins_switch);
432 table = IPTR->dst.table;
433 i = IPTR->sx.s23.s3.tablehigh
434 - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
444 case ICMD_LOOKUPSWITCH: /* {ALL} */
446 TYPECHECK_COUNT(stat_ins_switch);
448 lookup = IPTR->dst.lookup;
449 i = IPTR->sx.s23.s2.lookupcount;
450 REACH(IPTR->sx.s23.s3.lookupdefault);
453 REACH(lookup->target);
461 /****************************************/
462 /* ADDRESS RETURNS AND THROW */
465 TYPECHECK_COUNT(stat_ins_athrow);
466 r = typeinfo_is_assignable_to_class(&OP1->typeinfo,
467 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
468 if (r == typecheck_FALSE)
469 VERIFY_ERROR("illegal instruction: ATHROW on non-Throwable");
470 if (r == typecheck_FAIL)
472 if (r == typecheck_MAYBE) {
473 /* the check has to be postponed. we need a patcher */
474 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
475 IPTR->sx.s23.s2.uc = create_unresolved_class(
477 /* XXX make this more efficient, use class_java_lang_Throwable
479 class_get_classref(METHOD->clazz,utf_java_lang_Throwable),
481 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
486 TYPECHECK_COUNT(stat_ins_areturn);
487 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
488 VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
490 if (STATE->returntype.type != TYPE_ADR
491 || (r = typeinfo_is_assignable(&OP1->typeinfo,&(STATE->returntype.typeinfo)))
493 VERIFY_ERROR("Return type mismatch");
494 if (r == typecheck_FAIL)
496 if (r == typecheck_MAYBE) {
497 /* the check has to be postponed, we need a patcher */
498 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
499 IPTR->sx.s23.s2.uc = create_unresolved_class(
501 METHOD->parseddesc->returntype.classref,
503 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
507 /****************************************/
508 /* PRIMITIVE RETURNS */
511 if (STATE->returntype.type != TYPE_INT)
512 VERIFY_ERROR("Return type mismatch");
516 if (STATE->returntype.type != TYPE_LNG)
517 VERIFY_ERROR("Return type mismatch");
521 if (STATE->returntype.type != TYPE_FLT)
522 VERIFY_ERROR("Return type mismatch");
526 if (STATE->returntype.type != TYPE_DBL)
527 VERIFY_ERROR("Return type mismatch");
531 if (STATE->returntype.type != TYPE_VOID)
532 VERIFY_ERROR("Return type mismatch");
535 TYPECHECK_COUNT(stat_ins_primitive_return);
537 if (STATE->initmethod && METHOD->clazz != class_java_lang_Object) {
538 /* Check if the 'this' instance has been initialized. */
539 LOG("Checking <init> marker");
540 #if defined(TYPECHECK_VARIABLESBASED)
541 if (!typevector_checktype(jd->var,STATE->numlocals-1,TYPE_INT))
543 if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
545 VERIFY_ERROR("<init> method does not initialize 'this'");
549 /****************************************/
550 /* SUBROUTINE INSTRUCTIONS */
552 case ICMD_JSR: /* {VARIABLESBASED,TYPEINFERER} */
553 TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
554 REACH(IPTR->sx.s23.s3.jsrtarget);
557 case ICMD_JSR: /* {STACKBASED} */
559 tbptr = IPTR->sx.s23.s3.jsrtarget.block;
561 TYPEINFO_INIT_RETURNADDRESS(stack[0].typeinfo, tbptr);
564 stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
569 case ICMD_RET: /* {VARIABLESBASED,TYPEINFERER} */
570 #if !defined(TYPECHECK_TYPEINFERER)
571 /* check returnAddress variable */
572 if (!typevector_checkretaddr(jd->var,IPTR->s1.varindex))
573 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
578 case ICMD_RET: /* {STACKBASED} */
580 CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_RET);
581 if (!TYPEINFO_IS_PRIMITIVE(STATE->locals[IPTR->s1.varindex].typeinfo))
582 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
584 if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
588 /****************************************/
591 case ICMD_INVOKEVIRTUAL: /* {VARIABLESBASED,TYPEINFERER} */
592 case ICMD_INVOKESPECIAL: /* {VARIABLESBASED,TYPEINFERER} */
593 case ICMD_INVOKESTATIC: /* {VARIABLESBASED,TYPEINFERER} */
594 case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED,TYPEINFERER} */
595 TYPECHECK_COUNT(stat_ins_invoke);
596 if (!handle_invocation(state))
598 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
601 case ICMD_INVOKEVIRTUAL: /* {STACKBASED} */
602 case ICMD_INVOKESPECIAL: /* {STACKBASED} */
603 case ICMD_INVOKESTATIC: /* {STACKBASED} */
604 case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
605 TYPECHECK_COUNT(stat_ins_invoke);
607 INSTRUCTION_GET_METHODDESC(IPTR, md);
608 CHECK_STACK_DEPTH(md->paramslots);
610 if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
613 stack -= md->paramslots;
615 if (md->returntype.type != TYPE_VOID) {
616 if (IS_2_WORD_TYPE(md->returntype.type)) {
617 CHECK_STACK_SPACE(2);
619 stack[0].type = TYPE_VOID;
620 stack[-1].type = md->returntype.type;
623 CHECK_STACK_SPACE(1);
625 stack[0].type = md->returntype.type;
628 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
631 /****************************************/
634 case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED,TYPEINFERER} */
635 if (!handle_multianewarray(STATE))
639 case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
640 if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
642 stack -= (IPTR->s1.argcount - 1);
643 stack[0].type = TYPE_ADR;
646 /****************************************/
649 case ICMD_BUILTIN: /* {VARIABLESBASED,TYPEINFERER} */
650 TYPECHECK_COUNT(stat_ins_builtin);
651 if (!handle_builtin(state))
655 case ICMD_BUILTIN: /* {STACKBASED} */
656 TYPECHECK_COUNT(stat_ins_builtin);
657 if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
660 /* pop operands and push return value */
662 u1 rtype = IPTR->sx.s23.s3.bte->md->returntype.type;
663 stack -= IPTR->sx.s23.s3.bte->md->paramslots;
664 if (rtype != TYPE_VOID) {
665 if (IS_2_WORD_TYPE(rtype))
673 /* the following code is only used by the stackbased verifier */
675 case ICMD_POP: /* {STACKBASED} */
677 CHECK_CAT1(stack[0]);
680 case ICMD_POP2: /* {STACKBASED} */
681 /* we pop either 11 or 2 */
682 if (IS_CAT1(stack[0]))
683 CHECK_CAT1(stack[-1]);
686 case ICMD_SWAP: /* {STACKBASED} */
687 CHECK_CAT1(stack[0]);
688 CHECK_CAT1(stack[-1]);
690 COPY_SLOT(stack[ 0], temp );
691 COPY_SLOT(stack[-1], stack[ 0]);
692 COPY_SLOT(temp , stack[-1]);
695 case ICMD_DUP: /* {STACKBASED} */
697 CHECK_CAT1(stack[0]);
699 COPY_SLOT(stack[ 0], stack[ 1]);
702 case ICMD_DUP_X1: /* {STACKBASED} */
704 CHECK_CAT1(stack[0]);
706 CHECK_CAT1(stack[-1]);
708 COPY_SLOT(stack[ 0], stack[ 1]);
709 COPY_SLOT(stack[-1], stack[ 0]);
710 COPY_SLOT(stack[ 1], stack[-1]);
713 case ICMD_DUP_X2: /* {STACKBASED} */
715 CHECK_CAT1(stack[0]);
716 /* we skip either 11 or 2 */
717 if (IS_CAT1(stack[-1]))
718 CHECK_CAT1(stack[-2]);
720 COPY_SLOT(stack[ 0], stack[ 1]);
721 COPY_SLOT(stack[-1], stack[ 0]);
722 COPY_SLOT(stack[-2], stack[-1]);
723 COPY_SLOT(stack[ 1], stack[-2]);
726 case ICMD_DUP2: /* {STACKBASED} */
727 /* we dup either 11 or 2 */
728 if (IS_CAT1(stack[0]))
729 CHECK_CAT1(stack[-1]);
731 COPY_SLOT(stack[ 0], stack[ 2]);
732 COPY_SLOT(stack[-1], stack[ 1]);
735 case ICMD_DUP2_X1: /* {STACKBASED} */
736 /* we dup either 11 or 2 */
737 if (IS_CAT1(stack[0]))
738 CHECK_CAT1(stack[-1]);
740 CHECK_CAT1(stack[-2]);
742 COPY_SLOT(stack[ 0], stack[ 2]);
743 COPY_SLOT(stack[-1], stack[ 1]);
744 COPY_SLOT(stack[-2], stack[ 0]);
745 COPY_SLOT(stack[ 2], stack[-1]);
746 COPY_SLOT(stack[ 1], stack[-2]);
749 case ICMD_DUP2_X2: /* {STACKBASED} */
750 /* we dup either 11 or 2 */
751 if (IS_CAT1(stack[0]))
752 CHECK_CAT1(stack[-1]);
753 /* we skip either 11 or 2 */
754 if (IS_CAT1(stack[-2]))
755 CHECK_CAT1(stack[-3]);
757 COPY_SLOT(stack[ 0], stack[ 2]);
758 COPY_SLOT(stack[-1], stack[ 1]);
759 COPY_SLOT(stack[-2], stack[ 0]);
760 COPY_SLOT(stack[-3], stack[-1]);
761 COPY_SLOT(stack[ 2], stack[-2]);
762 COPY_SLOT(stack[ 1], stack[-3]);
766 /* this marker is needed by generate.pl: */
770 * These are local overrides for various environment variables in Emacs.
771 * Please do not remove this and leave it at the end of the file, where
772 * Emacs will automagically detect them.
773 * ---------------------------------------------------------------------
776 * indent-tabs-mode: t
780 * vim:noexpandtab:sw=4:ts=4: