1 /* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
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)
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:
38 */ case ICMD_CONSTANT: /* {TAG, TAG, ...} */
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
46 * If no tag is specified, {STACKBASED,VARIABLESBASED} is assumed.
48 * There are also tags that can be used inside a clause like this:
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.)
57 * The following macros are pre-defined:
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
63 /******************************************************************************/
64 #endif /* (end #if 0) */
67 /* this marker is needed by generate.pl: */
70 /****************************************/
73 /* We just need to copy the typeinfo */
74 /* for slots containing addresses. */
76 /* (These are only used by the variables based verifier.) */
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;
85 /****************************************/
86 /* LOADING ADDRESS FROM VARIABLE */
88 case ICMD_ALOAD: /* {ALL} */
89 TYPECHECK_COUNT(stat_ins_aload);
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");
97 TYPEINFO_COPY(OP1->typeinfo,DST->typeinfo);
100 /****************************************/
101 /* STORING ADDRESS TO VARIABLE */
103 case ICMD_ASTORE: /* {ALL} */
104 TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
107 /****************************************/
108 /* LOADING ADDRESS FROM ARRAY */
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");
116 if (!typeinfo_init_component(&OP1->typeinfo,&DST->typeinfo))
120 /****************************************/
123 case ICMD_PUTFIELD: /* {STACKBASED} */
124 CHECK_STACK_DEPTH(2);
125 if (!IS_CAT1(stack[0])) {
126 CHECK_STACK_DEPTH(3);
129 CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
130 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
135 case ICMD_PUTSTATIC: /* {STACKBASED} */
136 CHECK_STACK_DEPTH(1);
137 if (!IS_CAT1(stack[0])) {
138 /* (stack depth >= 2 is guaranteed) */
141 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
146 case ICMD_GETFIELD: /* {STACKBASED} */
147 CHECK_STACK_TYPE(stack[0], TYPE_ADR);
148 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
153 case ICMD_GETSTATIC: /* {STACKBASED} */
154 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
159 case ICMD_PUTFIELD: /* {VARIABLESBASED} */
160 if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
165 case ICMD_PUTSTATIC: /* {VARIABLESBASED} */
166 if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
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;
180 assert(cc->state & CLASS_LINKED);
181 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
184 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
187 if (!handle_fieldaccess(state, VAROP(iptr->s1), &constvalue))
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;
201 assert(cc->state & CLASS_LINKED);
202 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
205 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
208 if (!handle_fieldaccess(state, NULL, &constvalue))
213 case ICMD_GETFIELD: /* {VARIABLESBASED,TYPEINFERER} */
214 if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
219 case ICMD_GETSTATIC: /* {VARIABLESBASED,TYPEINFERER} */
220 if (!handle_fieldaccess(state, NULL, NULL))
225 /****************************************/
226 /* PRIMITIVE ARRAY ACCESS */
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");
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");
241 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
242 VERIFY_ERROR("Array type mismatch");
246 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
247 VERIFY_ERROR("Array type mismatch");
251 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
252 VERIFY_ERROR("Array type mismatch");
256 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
257 VERIFY_ERROR("Array type mismatch");
261 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
262 VERIFY_ERROR("Array type mismatch");
266 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
267 VERIFY_ERROR("Array type mismatch");
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");
277 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
278 VERIFY_ERROR("Array type mismatch");
282 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
283 VERIFY_ERROR("Array type mismatch");
287 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
288 VERIFY_ERROR("Array type mismatch");
292 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
293 VERIFY_ERROR("Array type mismatch");
297 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
298 VERIFY_ERROR("Array type mismatch");
302 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
303 VERIFY_ERROR("Array type mismatch");
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");
315 case ICMD_IASTORECONST:
316 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_INT))
317 VERIFY_ERROR("Array type mismatch");
320 case ICMD_LASTORECONST:
321 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_LONG))
322 VERIFY_ERROR("Array type mismatch");
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");
331 case ICMD_CASTORECONST:
332 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_CHAR))
333 VERIFY_ERROR("Array type mismatch");
336 case ICMD_SASTORECONST:
337 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_SHORT))
338 VERIFY_ERROR("Array type mismatch");
341 /****************************************/
342 /* ADDRESS CONSTANTS */
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);
350 if (IPTR->sx.val.anyptr == NULL)
351 TYPEINFO_INIT_NULLTYPE(DST->typeinfo);
353 /* string constant (or constant for builtin function) */
354 typeinfo_init_classinfo(&(DST->typeinfo),class_java_lang_String);
359 /****************************************/
360 /* CHECKCAST AND INSTANCEOF */
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");
369 /* XXX only if narrower */
370 if (!typeinfo_init_class(&(DST->typeinfo),IPTR->sx.s23.s3.c))
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");
379 /* XXX should propagate type information to the following if-branches */
382 /****************************************/
383 /* BRANCH INSTRUCTIONS */
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} */
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} */
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} */
417 TYPECHECK_COUNT(stat_ins_branch);
419 /* propagate stack and variables to the target block */
423 /****************************************/
426 case ICMD_TABLESWITCH: /* {ALL} */
428 TYPECHECK_COUNT(stat_ins_switch);
430 table = IPTR->dst.table;
431 i = IPTR->sx.s23.s3.tablehigh
432 - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
442 case ICMD_LOOKUPSWITCH: /* {ALL} */
444 TYPECHECK_COUNT(stat_ins_switch);
446 lookup = IPTR->dst.lookup;
447 i = IPTR->sx.s23.s2.lookupcount;
448 REACH(IPTR->sx.s23.s3.lookupdefault);
451 REACH(lookup->target);
459 /****************************************/
460 /* ADDRESS RETURNS AND THROW */
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)
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(
475 /* XXX make this more efficient, use class_java_lang_Throwable
477 class_get_classref(METHOD->clazz,utf_java_lang_Throwable),
479 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
484 TYPECHECK_COUNT(stat_ins_areturn);
485 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
486 VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
488 if (STATE->returntype.type != TYPE_ADR
489 || (r = typeinfo_is_assignable(&OP1->typeinfo,&(STATE->returntype.typeinfo)))
491 VERIFY_ERROR("Return type mismatch");
492 if (r == typecheck_FAIL)
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(
499 METHOD->parseddesc->returntype.classref,
501 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
505 /****************************************/
506 /* PRIMITIVE RETURNS */
509 if (STATE->returntype.type != TYPE_INT)
510 VERIFY_ERROR("Return type mismatch");
514 if (STATE->returntype.type != TYPE_LNG)
515 VERIFY_ERROR("Return type mismatch");
519 if (STATE->returntype.type != TYPE_FLT)
520 VERIFY_ERROR("Return type mismatch");
524 if (STATE->returntype.type != TYPE_DBL)
525 VERIFY_ERROR("Return type mismatch");
529 if (STATE->returntype.type != TYPE_VOID)
530 VERIFY_ERROR("Return type mismatch");
533 TYPECHECK_COUNT(stat_ins_primitive_return);
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))
541 if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
543 VERIFY_ERROR("<init> method does not initialize 'this'");
547 /****************************************/
548 /* SUBROUTINE INSTRUCTIONS */
550 case ICMD_JSR: /* {VARIABLESBASED,TYPEINFERER} */
551 TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
552 REACH(IPTR->sx.s23.s3.jsrtarget);
555 case ICMD_JSR: /* {STACKBASED} */
557 tbptr = IPTR->sx.s23.s3.jsrtarget.block;
559 TYPEINFO_INIT_RETURNADDRESS(stack[0].typeinfo, tbptr);
562 stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
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");
576 case ICMD_RET: /* {STACKBASED} */
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");
582 if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
586 /****************************************/
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))
596 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
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);
605 INSTRUCTION_GET_METHODDESC(IPTR, md);
606 CHECK_STACK_DEPTH(md->paramslots);
608 if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
611 stack -= md->paramslots;
613 if (md->returntype.type != TYPE_VOID) {
614 if (IS_2_WORD_TYPE(md->returntype.type)) {
615 CHECK_STACK_SPACE(2);
617 stack[0].type = TYPE_VOID;
618 stack[-1].type = md->returntype.type;
621 CHECK_STACK_SPACE(1);
623 stack[0].type = md->returntype.type;
626 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
629 /****************************************/
632 case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED,TYPEINFERER} */
633 if (!handle_multianewarray(STATE))
637 case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
638 if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
640 stack -= (IPTR->s1.argcount - 1);
641 stack[0].type = TYPE_ADR;
644 /****************************************/
647 case ICMD_BUILTIN: /* {VARIABLESBASED,TYPEINFERER} */
648 TYPECHECK_COUNT(stat_ins_builtin);
649 if (!handle_builtin(state))
653 case ICMD_BUILTIN: /* {STACKBASED} */
654 TYPECHECK_COUNT(stat_ins_builtin);
655 if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
658 /* pop operands and push return value */
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))
671 /* the following code is only used by the stackbased verifier */
673 case ICMD_POP: /* {STACKBASED} */
675 CHECK_CAT1(stack[0]);
678 case ICMD_POP2: /* {STACKBASED} */
679 /* we pop either 11 or 2 */
680 if (IS_CAT1(stack[0]))
681 CHECK_CAT1(stack[-1]);
684 case ICMD_SWAP: /* {STACKBASED} */
685 CHECK_CAT1(stack[0]);
686 CHECK_CAT1(stack[-1]);
688 COPY_SLOT(stack[ 0], temp );
689 COPY_SLOT(stack[-1], stack[ 0]);
690 COPY_SLOT(temp , stack[-1]);
693 case ICMD_DUP: /* {STACKBASED} */
695 CHECK_CAT1(stack[0]);
697 COPY_SLOT(stack[ 0], stack[ 1]);
700 case ICMD_DUP_X1: /* {STACKBASED} */
702 CHECK_CAT1(stack[0]);
704 CHECK_CAT1(stack[-1]);
706 COPY_SLOT(stack[ 0], stack[ 1]);
707 COPY_SLOT(stack[-1], stack[ 0]);
708 COPY_SLOT(stack[ 1], stack[-1]);
711 case ICMD_DUP_X2: /* {STACKBASED} */
713 CHECK_CAT1(stack[0]);
714 /* we skip either 11 or 2 */
715 if (IS_CAT1(stack[-1]))
716 CHECK_CAT1(stack[-2]);
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]);
724 case ICMD_DUP2: /* {STACKBASED} */
725 /* we dup either 11 or 2 */
726 if (IS_CAT1(stack[0]))
727 CHECK_CAT1(stack[-1]);
729 COPY_SLOT(stack[ 0], stack[ 2]);
730 COPY_SLOT(stack[-1], stack[ 1]);
733 case ICMD_DUP2_X1: /* {STACKBASED} */
734 /* we dup either 11 or 2 */
735 if (IS_CAT1(stack[0]))
736 CHECK_CAT1(stack[-1]);
738 CHECK_CAT1(stack[-2]);
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]);
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]);
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]);
764 /* this marker is needed by generate.pl: */
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 * ---------------------------------------------------------------------
774 * indent-tabs-mode: t
778 * vim:noexpandtab:sw=4:ts=4: