[kaffe] CVS kaffe (rob): kaffe/kaffevm/verifier/verify3a.c
Kaffe CVS
cvs-commits at kaffe.org
Fri Jul 2 12:29:47 PDT 2004
PatchSet 4883
Date: 2004/07/02 19:23:59
Author: rob
Branch: HEAD
Tag: (none)
Log:
* kaffe/kaffevm/verifier/verify3a.c
* kaffe/kaffevm/verifier/verify3b.c
Added to break up verify.c into passes 3a and 3b.
* kaffe/kaffevm/verifier/verify-errors.h
Verify pass 3a error methods moved to verify3a.c
* kaffe/kaffevm/verifier/verify-block.c
(verifyBasicBlock) Moved in from verify.c.
* kaffe/kaffevm/verifier/verify.h
Method and variable prototypes formerly declared
"static" in verify.c moved here for use in the new
newly partitioned verifier sections.
* kaffe/kaffevm/verifier/verify.c
(verifyMethod3a) moved to verify3a.c
(verifyMethod3b) moved to verify3b.c
(mergeBasicBlocks) moved to verfiy3b.c
(verifyBasicBlock) moved to verify-block.c
Some error helper methods moved along with the
methods they helped.
* kaffe/kaffevm/verifier/Makefile.am
* kaffe/kaffevm/verifier/Makefile.in
Regenerated (i.e. fixed by hand because I don't
have automake 1.8.5).
Members:
ChangeLog:1.2449->1.2450
kaffe/kaffevm/verifier/Makefile.am:1.3->1.4
kaffe/kaffevm/verifier/Makefile.in:1.4->1.5
kaffe/kaffevm/verifier/verify-block.c:1.1->1.2
kaffe/kaffevm/verifier/verify-errors.h:1.3->1.4
kaffe/kaffevm/verifier/verify.c:1.4->1.5
kaffe/kaffevm/verifier/verify.h:1.3->1.4
kaffe/kaffevm/verifier/verify3a.c:INITIAL->1.1
kaffe/kaffevm/verifier/verify3b.c:INITIAL->1.1
Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2449 kaffe/ChangeLog:1.2450
--- kaffe/ChangeLog:1.2449 Fri Jul 2 17:17:54 2004
+++ kaffe/ChangeLog Fri Jul 2 19:23:59 2004
@@ -1,4 +1,34 @@
2004-07-01 Rob Gonzalez <rob at kaffe.org>
+ * kaffe/kaffevm/verifier/verify3a.c
+ * kaffe/kaffevm/verifier/verify3b.c
+ Added to break up verify.c into passes 3a and 3b.
+
+ * kaffe/kaffevm/verifier/verify-errors.h
+ Verify pass 3a error methods moved to verify3a.c
+
+ * kaffe/kaffevm/verifier/verify-block.c
+ (verifyBasicBlock) Moved in from verify.c.
+
+ * kaffe/kaffevm/verifier/verify.h
+ Method and variable prototypes formerly declared
+ "static" in verify.c moved here for use in the new
+ newly partitioned verifier sections.
+
+ * kaffe/kaffevm/verifier/verify.c
+ (verifyMethod3a) moved to verify3a.c
+ (verifyMethod3b) moved to verify3b.c
+ (mergeBasicBlocks) moved to verfiy3b.c
+ (verifyBasicBlock) moved to verify-block.c
+
+ Some error helper methods moved along with the
+ methods they helped.
+
+ * kaffe/kaffevm/verifier/Makefile.am
+ * kaffe/kaffevm/verifier/Makefile.in
+ Regenerated (i.e. fixed by hand because I don't
+ have automake 1.8.5).
+
+2004-07-01 Rob Gonzalez <rob at kaffe.org>
* kaffe/kaffevm/verifier/verify-types.c
An extra ';' removed that was causing older gcc's trouble.
Index: kaffe/kaffe/kaffevm/verifier/Makefile.am
diff -u kaffe/kaffe/kaffevm/verifier/Makefile.am:1.3 kaffe/kaffe/kaffevm/verifier/Makefile.am:1.4
--- kaffe/kaffe/kaffevm/verifier/Makefile.am:1.3 Tue Jun 29 13:06:57 2004
+++ kaffe/kaffe/kaffevm/verifier/Makefile.am Fri Jul 2 19:24:03 2004
@@ -32,6 +32,8 @@
verify.c \
verify.h \
verify2.c \
+ verify3a.c \
+ verify3b.c \
verify-block.c \
verify-block.h \
verify-debug.c \
Index: kaffe/kaffe/kaffevm/verifier/Makefile.in
diff -u kaffe/kaffe/kaffevm/verifier/Makefile.in:1.4 kaffe/kaffe/kaffevm/verifier/Makefile.in:1.5
--- kaffe/kaffe/kaffevm/verifier/Makefile.in:1.4 Tue Jun 29 13:06:57 2004
+++ kaffe/kaffe/kaffevm/verifier/Makefile.in Fri Jul 2 19:24:03 2004
@@ -74,7 +74,8 @@
nativeLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(native_LTLIBRARIES)
libkaffeverifier_la_LIBADD =
-am_libkaffeverifier_la_OBJECTS = verify.lo verify2.lo verify-block.lo \
+am_libkaffeverifier_la_OBJECTS = verify.lo verify2.lo \
+ verify3a.lo verify3b.lo verify-block.lo \
verify-debug.lo verify-sigstack.lo verify-type.lo \
verify-uninit.lo
libkaffeverifier_la_OBJECTS = $(am_libkaffeverifier_la_OBJECTS)
@@ -86,7 +87,9 @@
@AMDEP_TRUE@ ./$(DEPDIR)/verify-sigstack.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/verify-type.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/verify-uninit.Plo \
- at AMDEP_TRUE@ ./$(DEPDIR)/verify.Plo ./$(DEPDIR)/verify2.Plo
+ at AMDEP_TRUE@ ./$(DEPDIR)/verify.Plo ./$(DEPDIR)/verify2.Plo \
+ at AMDEP_TRUE@ ./$(DEPDIR)/verify3a.Plo \
+ at AMDEP_TRUE@ ./$(DEPDIR)/verify3b.Plo
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
@@ -368,6 +371,8 @@
verify.c \
verify.h \
verify2.c \
+ verify3a.c \
+ verify3b.c \
verify-block.c \
verify-block.h \
verify-debug.c \
@@ -456,6 +461,8 @@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/verify-uninit.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/verify.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/verify2.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/verify3a.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/verify3b.Plo at am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
Index: kaffe/kaffe/kaffevm/verifier/verify-block.c
diff -u kaffe/kaffe/kaffevm/verifier/verify-block.c:1.1 kaffe/kaffe/kaffevm/verifier/verify-block.c:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-block.c:1.1 Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-block.c Fri Jul 2 19:24:03 2004
@@ -10,8 +10,29 @@
* Code for handing of blocks in the verifier.
*/
+#include "bytecode.h"
+#include "baseClasses.h"
+#include "classMethod.h"
+#include "code.h"
+#include "constants.h"
#include "debug.h"
+#include "errors.h"
+#include "exception.h"
+#include "gc.h"
+#include "itypes.h"
+
+#include "verify.h"
#include "verify-block.h"
+#include "verify-debug.h"
+#include "verify-errors.h"
+#include "verify-sigstack.h"
+#include "verify-type.h"
+#include "verify-uninit.h"
+
+
+/*********************************************************
+ * BASIC BLOCK MEMORY MANAGEMENT
+ *********************************************************/
/*
* allocate memory for a block info and fill in with default values
@@ -118,4 +139,1477 @@
DBG(VERIFY3, dprintf("inWhichBlock(...): pc = %d out of range...weird.\n", pc); );
return NULL;
+}
+
+
+/*********************************************************
+ * BASIC BLOCK VERIFICATION
+ *********************************************************/
+/*
+ * Helper function for error reporting in ENSURE_LOCAL_TYPE macro in verifyBasicBlock.
+ */
+static inline
+bool
+ensureLocalTypeErrorInVerifyBasicBlock(Verifier* v,
+ const BlockInfo* block,
+ const unsigned int n)
+{
+ if (block->locals[n].data.class == TUNSTABLE->data.class) {
+ return verifyError(v, "attempt to access an unstable local variable");
+ } else {
+ return verifyError(v, "attempt to access a local variable not of the correct type");
+ }
+}
+
+/*
+ * Helper function for error reporting in ENSURE_OPSTACK_SIZE macro in verifyBasicBlock.
+ */
+static inline
+bool
+ensureOpstackSizeErrorInVerifyBasicBlock(Verifier* v,
+ const BlockInfo* block)
+
+{
+ DBG(VERIFY3,
+ dprintf(" here's the stack: \n");
+ printBlock(v->method, block, " ");
+ );
+ return verifyError(v, "not enough items on stack for operation");
+}
+
+/*
+ * Helper function for error reporting in CHECK_STACK_OVERFLOW macro in verifyBasicBlock.
+ */
+static inline
+bool
+checkStackOverflowErrorInVerifyBasicBlock(Verifier* v,
+ const BlockInfo* block,
+ const unsigned int n)
+{
+ DBG(VERIFY3,
+ dprintf(" block->stacksz: %d :: N = %d :: method->stacksz = %d\n",
+ block->stacksz,
+ n,
+ v->method->stacksz);
+ );
+ DBG(VERIFY3,
+ dprintf(" here's the stack: \n");
+ printBlock(v->method, block, " ");
+ );
+ return verifyError(v, "stack overflow");
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ *
+ * @return nth item on the operand stack from the top.
+ */
+static inline
+Type *
+getOpstackItem(BlockInfo* block,
+ unsigned int n)
+{
+ return (&block->opstack[block->stacksz - n]);
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ *
+ * @return first item on the operand stack from the top.
+ */
+static inline
+Type *
+getOpstackTop(BlockInfo* block)
+{
+ return getOpstackItem(block, 1);
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ *
+ * @return second item on the operand stack from the top.
+ */
+static inline
+Type *
+getOpstackWTop(BlockInfo* block)
+{
+ return getOpstackItem(block, 2);
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ */
+static inline
+void
+opstackPushBlind(BlockInfo* block,
+ const Type* type)
+{
+ block->opstack[block->stacksz++] = *(type);
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ * only use for LONGs and DOUBLEs.
+ */
+static inline
+void
+opstackWPushBlind(BlockInfo* block,
+ const Type* type)
+{
+ opstackPushBlind(block, type);
+ opstackPushBlind(block, TWIDE);
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ */
+static inline
+void
+opstackPopBlind(BlockInfo* block)
+{
+ block->stacksz--;
+ block->opstack[block->stacksz] = *TUNSTABLE;
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ */
+static inline
+void
+opstackWPopBlind(BlockInfo* block)
+{
+ opstackPopBlind(block);
+ opstackPopBlind(block);
+}
+
+/*
+ * Helper function for opstack access in verifyBasicBlock.
+ * pop _N things off the stack off the stack.
+ */
+static inline
+void
+opstackPopNBlind(BlockInfo* block,
+ unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; ++i) {
+ opstackPopBlind(block);
+ }
+}
+
+/*
+ * Helper function for error reporting in OPSTACK_PEEK_T_BLIND macro in verifyBasicBlock.
+ */
+static inline
+bool
+opstackPeekTBlindErrorInVerifyBasicBlock(Verifier* v,
+ BlockInfo* block,
+ const Type* type)
+{
+ DBG(VERIFY3,
+ dprintf(" OPSTACK_TOP: ");
+ printType(getOpstackTop(block));
+ dprintf(" vs. what's we wanted: ");
+ printType(type);
+ dprintf("\n");
+ );
+ return verifyError(v, "top of opstack does not have desired type");
+}
+
+/*
+ * verifyBasicBlock()
+ * Simulates execution of a basic block by modifying its
+ * simulated operand stack and local variable array.
+ *
+ * TODO: turn at least some of the macros into static
+ * inline methods
+ */
+bool
+verifyBasicBlock(Verifier* v, BlockInfo* block)
+{
+ /**************************************************************************************************
+ * VARIABLES
+ **************************************************************************************************/
+ uint32 pc = 0;
+ unsigned char* code = METHOD_BYTECODE_CODE(v->method);
+
+ bool wide = false; /* was the previous opcode a WIDE instruction? */
+
+ uint32 n = 0; /* used as a general temporary variable, often as a temporary pc */
+
+ Type* type = NULL;
+ Type* arrayType = NULL;
+ Hjava_lang_Class* class; /* for when we need a pointer to an actual class */
+
+ /* for the rare occasions when we actually need a Type */
+ Type tt;
+ Type* t = &tt;
+
+ int tag; /* used for constant tag stuff */
+
+ uint32 idx; /* index into constant pool */
+ const constants* pool = CLASS_CONSTANTS(v->class);
+
+ const char* sig;
+
+
+ /**************************************************************************************************
+ * HANDY MACROS USED ONLY IN THIS METHOD
+ * most of these belong to one of two categories:
+ * - those dealing with locals variables
+ * - those dealing with the operand stack
+ **************************************************************************************************/
+
+#define GET_IDX \
+ idx = getIdx(code, pc)
+
+#define GET_WIDX \
+ idx = getWIdx(code, pc)
+
+
+ /* checks whether the specified local variable is of the specified type. */
+#define ENSURE_LOCAL_TYPE(_N, _TINFO) \
+ if (!typecheck(v, (_TINFO), &block->locals[_N])) { \
+ return ensureLocalTypeErrorInVerifyBasicBlock(v, block, _N); \
+ }
+
+ /* only use with TLONG and TDOUBLE */
+#define ENSURE_LOCAL_WTYPE(_N, _TINFO) \
+ if (block->locals[_N].data.class != (_TINFO)->data.class) { \
+ return verifyError(v, "local variable not of correct type"); \
+ } \
+ else if (block->locals[_N + 1].data.class != TWIDE->data.class) { \
+ return verifyError(v, "accessing a long or double in a local where the following local has been corrupted"); \
+ }
+
+
+#define ENSURE_OPSTACK_SIZE(_N) \
+ if (block->stacksz < (_N)) { \
+ return ensureOpstackSizeErrorInVerifyBasicBlock(v, block); \
+ }
+
+#define CHECK_STACK_OVERFLOW(_N) \
+ if (block->stacksz + _N > v->method->stacksz) { \
+ return checkStackOverflowErrorInVerifyBasicBlock(v, block, _N); \
+ }
+
+#define OPSTACK_PUSH(_TINFO) \
+ CHECK_STACK_OVERFLOW(1); \
+ opstackPushBlind(block, _TINFO)
+
+#define OPSTACK_WPUSH(_T) \
+ CHECK_STACK_OVERFLOW(2); \
+ opstackWPushBlind(block, _T)
+
+
+
+ /* ensure that the top item on the stack is of type _T */
+#define OPSTACK_PEEK_T_BLIND(_TINFO) \
+ if (!typecheck(v, _TINFO, getOpstackTop(block))) { \
+ return opstackPeekTBlindErrorInVerifyBasicBlock(v, block, _TINFO); \
+ }
+
+#define OPSTACK_PEEK_T(_TINFO) \
+ ENSURE_OPSTACK_SIZE(1); \
+ OPSTACK_PEEK_T_BLIND(_TINFO)
+
+ /* ensure that the top item on the stack is of wide type _T
+ * this only works with doubles and longs
+ */
+#define OPSTACK_WPEEK_T_BLIND(_TINFO) \
+ if (getOpstackTop(block)->data.class != TWIDE->data.class) { \
+ return verifyError(v, "trying to pop a wide value off operand stack where there is none"); \
+ } else if (getOpstackWTop(block)->data.class != (_TINFO)->data.class) { \
+ return verifyError(v, "mismatched stack types"); \
+ }
+
+#define OPSTACK_WPEEK_T(_TINFO) \
+ ENSURE_OPSTACK_SIZE(2); \
+ OPSTACK_WPEEK_T_BLIND(_TINFO)
+
+#define OPSTACK_POP \
+ ENSURE_OPSTACK_SIZE(1); \
+ opstackPopBlind(block)
+
+ /* pop a type off the stack and typecheck it */
+#define OPSTACK_POP_T_BLIND(_TINFO) \
+ OPSTACK_PEEK_T_BLIND(_TINFO); \
+ opstackPopBlind(block)
+
+#define OPSTACK_POP_T(_TINFO) \
+ OPSTACK_PEEK_T(_TINFO); \
+ opstackPopBlind(block)
+
+#define OPSTACK_WPOP \
+ ENSURE_OPSTACK_SIZE(2); \
+ opstackWPopBlind(block)
+
+ /* pop a wide type off the stack and typecheck it */
+#define OPSTACK_WPOP_T_BLIND(_TINFO) \
+ OPSTACK_WPEEK_T_BLIND(_TINFO); \
+ opstackWPopBlind(block)
+
+#define OPSTACK_WPOP_T(_TINFO) \
+ OPSTACK_WPEEK_T(_TINFO); \
+ opstackWPopBlind(block)
+
+#define OPSTACK_POP_N(_N) \
+ ENSURE_OPSTACK_SIZE(_N); \
+ opstackPopNBlind(block, _N)
+
+
+
+ /**************************************************************************************************
+ * BLOCK-LEVEL DATA FLOW ANALYASIS
+ * this is actually pretty easy, since there are never any branches. basically, it just
+ * manipulates the working stack after every instruction as if it were actually running the
+ * code so that, after verifying the block, the working block can be used to merge this block
+ * with its successors.
+ **************************************************************************************************/
+ DBG(VERIFY3,
+ dprintf(" about to verify the block...\n");
+ dprintf(" block->startAddr = %d, block->lastAddr = %d, first instruction = %d\n",
+ block->startAddr, block->lastAddr, code[block->startAddr]);
+ );
+
+ pc = block->startAddr;
+ while (pc <= block->lastAddr) {
+ DBG(VERIFY3,
+ dprintf(" pc = %d, opcode = %d == ", pc, code[pc]);
+ printInstruction(code[pc]);
+ dprintf("\n");
+ );
+
+ switch(code[pc]) {
+ /**************************************************************
+ * INSTRUCTIONS FOR PUSHING CONSTANTS ONTO THE STACK
+ **************************************************************/
+ /* pushes NULL onto the stack, which matches any object */
+ case ACONST_NULL:
+ OPSTACK_PUSH(TNULL);
+ break;
+
+ /* iconst_<n> pushes n onto the stack */
+ case ICONST_0: case ICONST_1: case ICONST_2:
+ case ICONST_3: case ICONST_4: case ICONST_5:
+
+ case ICONST_M1: /* pushes -1 onto the stack */
+ case BIPUSH: /* sign extends an 8-bit int to 32-bits and pushes it onto stack */
+ case SIPUSH: /* sign extends a 16-bit int to 32-bits and pushes it onto stack */
+ OPSTACK_PUSH(TINT);
+ break;
+
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ OPSTACK_PUSH(TFLOAT);
+ break;
+
+ case LCONST_0:
+ case LCONST_1:
+ OPSTACK_WPUSH(TLONG);
+ break;
+
+ case DCONST_0:
+ case DCONST_1:
+ OPSTACK_WPUSH(TDOUBLE);
+ break;
+
+
+ case LDC1:
+ GET_IDX;
+ goto LDC_common;
+ case LDC2:
+ GET_WIDX;
+ LDC_common:
+ tag = CONST_TAG(idx, pool);
+ switch(tag) {
+ case CONSTANT_Integer: OPSTACK_PUSH(TINT); break;
+ case CONSTANT_Float: OPSTACK_PUSH(TFLOAT); break;
+ case CONSTANT_ResolvedString:
+ case CONSTANT_String:
+ /* we do this because we might be loading a class before
+ * loading String
+ */
+ OPSTACK_PUSH(TSTRING);
+ break;
+ }
+ break;
+
+ case LDC2W:
+ GET_WIDX;
+ tag = CONST_TAG(idx, pool);
+ if (tag == CONSTANT_Long) {
+ OPSTACK_WPUSH(TLONG);
+ } else {
+ OPSTACK_WPUSH(TDOUBLE);
+ }
+ break;
+
+
+ /**************************************************************
+ * INSTRUCTIONS DEALING WITH THE LOCALS AND STACK
+ **************************************************************/
+ case POP:
+ OPSTACK_POP;
+ break;
+ case POP2:
+ OPSTACK_WPOP;
+ break;
+
+
+#define GET_CONST_INDEX \
+ if (wide == true) { GET_WIDX; } \
+ else { GET_IDX; }
+
+
+ /* aload_<n> takes the object reference in location <n> and pushes it onto the stack */
+ case ALOAD_0: idx = 0; goto ALOAD_common;
+ case ALOAD_1: idx = 1; goto ALOAD_common;
+ case ALOAD_2: idx = 2; goto ALOAD_common;
+ case ALOAD_3: idx = 3; goto ALOAD_common;
+ case ALOAD:
+ GET_CONST_INDEX;
+ ALOAD_common:
+ if (!isReference(&block->locals[idx])) {
+ DBG(VERIFY3, dprintf("%sERROR: ", indent); printType(&block->locals[idx]); dprintf("\n"); );
+ return verifyError(v, "aload<_n> where local variable does not contain an object reference");
+ }
+
+ OPSTACK_PUSH(&block->locals[idx]);
+ break;
+
+
+ /* stores whatever's on the top of the stack in local <n> */
+ case ASTORE_0: idx = 0; goto ASTORE_common;
+ case ASTORE_1: idx = 1; goto ASTORE_common;
+ case ASTORE_2: idx = 2; goto ASTORE_common;
+ case ASTORE_3: idx = 3; goto ASTORE_common;
+ case ASTORE:
+ GET_CONST_INDEX;
+ ASTORE_common:
+ ENSURE_OPSTACK_SIZE(1);
+ type = getOpstackTop(block);
+
+ if (!IS_ADDRESS(type) && !isReference(type)) {
+ return verifyError(v, "astore: top of stack is not a return address or reference type");
+ }
+
+ block->locals[idx] = *type;
+ opstackPopBlind(block);
+ break;
+
+
+
+ /* iload_<n> takes the variable in location <n> and pushes it onto the stack */
+ case ILOAD_0: idx = 0; goto ILOAD_common;
+ case ILOAD_1: idx = 1; goto ILOAD_common;
+ case ILOAD_2: idx = 2; goto ILOAD_common;
+ case ILOAD_3: idx = 3; goto ILOAD_common;
+ case ILOAD:
+ GET_CONST_INDEX;
+ ILOAD_common:
+ ENSURE_LOCAL_TYPE(idx, TINT);
+ OPSTACK_PUSH(TINT);
+ break;
+
+
+ case ISTORE_0: idx =0; goto ISTORE_common;
+ case ISTORE_1: idx =1; goto ISTORE_common;
+ case ISTORE_2: idx =2; goto ISTORE_common;
+ case ISTORE_3: idx =3; goto ISTORE_common;
+ case ISTORE:
+ GET_CONST_INDEX;
+ ISTORE_common:
+ OPSTACK_POP_T(TINT);
+ block->locals[idx] = *TINT;
+ break;
+
+
+ /* fload_<n> takes the variable at location <n> and pushes it onto the stack */
+ case FLOAD_0: idx =0; goto FLOAD_common;
+ case FLOAD_1: idx =1; goto FLOAD_common;
+ case FLOAD_2: idx =2; goto FLOAD_common;
+ case FLOAD_3: idx = 3; goto FLOAD_common;
+ case FLOAD:
+ GET_CONST_INDEX;
+ FLOAD_common:
+ ENSURE_LOCAL_TYPE(idx, TFLOAT);
+ OPSTACK_PUSH(TFLOAT);
+ break;
+
+
+ /* stores a float from top of stack into local <n> */
+ case FSTORE_0: idx = 0; goto FSTORE_common;
+ case FSTORE_1: idx = 1; goto FSTORE_common;
+ case FSTORE_2: idx = 2; goto FSTORE_common;
+ case FSTORE_3: idx = 3; goto FSTORE_common;
+ case FSTORE:
+ GET_CONST_INDEX;
+ FSTORE_common:
+ OPSTACK_POP_T(TFLOAT);
+ block->locals[idx] = *TFLOAT;
+ break;
+
+
+ /* lload_<n> takes the variable at location <n> and pushes it onto the stack */
+ case LLOAD_0: idx = 0; goto LLOAD_common;
+ case LLOAD_1: idx = 1; goto LLOAD_common;
+ case LLOAD_2: idx = 2; goto LLOAD_common;
+ case LLOAD_3: idx = 3; goto LLOAD_common;
+ case LLOAD:
+ GET_CONST_INDEX;
+ LLOAD_common:
+ ENSURE_LOCAL_WTYPE(idx, TLONG);
+ OPSTACK_WPUSH(TLONG);
+ break;
+
+
+ /* lstore_<n> stores a long from top of stack into local <n> */
+ case LSTORE_0: idx = 0; goto LSTORE_common;
+ case LSTORE_1: idx = 1; goto LSTORE_common;
+ case LSTORE_2: idx = 2; goto LSTORE_common;
+ case LSTORE_3: idx = 3; goto LSTORE_common;
+ case LSTORE:
+ GET_CONST_INDEX;
+ LSTORE_common:
+ OPSTACK_WPOP_T(TLONG);
+ block->locals[idx] = *TLONG;
+ block->locals[idx + 1] = *TWIDE;
+ break;
+
+
+ /* dload_<n> takes the double at local <n> and pushes it onto the stack */
+ case DLOAD_0: idx = 0; goto DLOAD_common;
+ case DLOAD_1: idx = 1; goto DLOAD_common;
+ case DLOAD_2: idx = 2; goto DLOAD_common;
+ case DLOAD_3: idx = 3; goto DLOAD_common;
+ case DLOAD:
+ GET_CONST_INDEX;
+ DLOAD_common:
+ ENSURE_LOCAL_WTYPE(idx, TDOUBLE);
+ OPSTACK_WPUSH(TDOUBLE);
+ break;
+
+
+ /* dstore stores a double from the top of stack into a local variable */
+ case DSTORE_0: idx = 0; goto DSTORE_common;
+ case DSTORE_1: idx = 1; goto DSTORE_common;
+ case DSTORE_2: idx = 2; goto DSTORE_common;
+ case DSTORE_3: idx = 3; goto DSTORE_common;
+ case DSTORE:
+ GET_CONST_INDEX;
+ DSTORE_common:
+ OPSTACK_WPOP_T(TDOUBLE);
+ block->locals[idx] = *TDOUBLE;
+ block->locals[idx + 1] = *TWIDE;
+ break;
+
+
+#undef GET_CONST_INDEX
+ /**************************************************************
+ * ARRAY INSTRUCTIONS!
+ **************************************************************/
+ /* i put ANEWARRAY code by NEW instead of in the array instructions
+ * section because of similarities with NEW
+
+ * for creating a primitive array
+ */
+ case NEWARRAY:
+ OPSTACK_POP_T(TINT); /* array size */
+
+ switch(code[pc + 1]) {
+ case TYPE_Boolean: OPSTACK_PUSH(TBOOLARR); break;
+ case TYPE_Char: OPSTACK_PUSH(TCHARARR); break;
+ case TYPE_Float: OPSTACK_PUSH(TFLOATARR); break;
+ case TYPE_Double: OPSTACK_PUSH(TDOUBLEARR); break;
+ case TYPE_Byte: OPSTACK_PUSH(TBYTEARR); break;
+ case TYPE_Short: OPSTACK_PUSH(TSHORTARR); break;
+ case TYPE_Int: OPSTACK_PUSH(TINTARR); break;
+ case TYPE_Long: OPSTACK_PUSH(TLONGARR); break;
+ default: return verifyError(v, "newarray of unknown type");
+ }
+ break;
+
+ case ARRAYLENGTH:
+ ENSURE_OPSTACK_SIZE(1);
+
+ type = getOpstackTop(block);
+ if (!isArray(type)) {
+ DBG(VERIFY3, dprintf("%stype = ", indent); printType(type); dprintf("\n"); );
+ return verifyError(v, "arraylength: top of operand stack is not an array");
+ }
+
+ *type = *TINT;
+ break;
+
+
+#define ARRAY_LOAD(_T, _ARRT) \
+ OPSTACK_POP_T(TINT); \
+ OPSTACK_POP_T(_ARRT); \
+ OPSTACK_PUSH(_T);
+
+#define ARRAY_WLOAD(_T, _ARRT) \
+ OPSTACK_POP_T(TINT); \
+ OPSTACK_POP_T(_ARRT); \
+ OPSTACK_WPUSH(_T);
+
+
+ case AALOAD:
+ ENSURE_OPSTACK_SIZE(2);
+
+ if (getOpstackTop(block)->data.class != TINT->data.class) {
+ return verifyError(v, "aaload: item on top of stack is not an integer");
+ }
+ opstackPopBlind(block);
+
+ type = getOpstackTop(block);
+ if (!isArray(type)) {
+ DBG(VERIFY3, dprintf("%serror: type = ", indent); printType(type); dprintf("\n"); );
+ return verifyError(v, "aaload: top of operand stack is not an array");
+ }
+
+ if (type->tinfo & TINFO_NAME || type->tinfo & TINFO_SIG) {
+ type->tinfo = TINFO_SIG;
+ (type->data.sig)++;
+ }
+ else if (type->data.class != TNULL->data.class) {
+ type->tinfo = TINFO_SIG;
+ type->data.sig = CLASS_CNAME(type->data.class) + 1;
+ }
+ DBG(VERIFY3, dprintf("%sarray type: ", indent); printType(type); dprintf("\n"); );
+ break;
+
+ case IALOAD: ARRAY_LOAD(TINT, TINTARR); break;
+ case FALOAD: ARRAY_LOAD(TFLOAT, TFLOATARR); break;
+ case CALOAD: ARRAY_LOAD(TINT, TCHARARR); break;
+ case SALOAD: ARRAY_LOAD(TINT, TSHORTARR); break;
+
+ case LALOAD: ARRAY_WLOAD(TLONG, TLONGARR); break;
+ case DALOAD: ARRAY_WLOAD(TDOUBLE, TDOUBLEARR); break;
+#undef ARRAY_LOAD
+#undef ARRAY_WLOAD
+
+ case BALOAD:
+ /* BALOAD can be used for bytes or booleans .... */
+ OPSTACK_POP_T(TINT);
+
+ if (!typecheck (v, TBYTEARR, getOpstackTop(block)) &&
+ !typecheck (v, TBOOLARR, getOpstackTop(block))) {
+ DBG(VERIFY3,
+ dprintf(" OPSTACK_TOP: ");
+ printType(getOpstackTop(block));
+ dprintf(" vs. what's we wanted: TBYTEARR or TBOOLARR"); )
+ return verifyError(v, "top of opstack does not have desired type");
+ }
+
+ opstackPopBlind(block);
+ OPSTACK_PUSH(TINT);
+ break;
+
+
+ case AASTORE:
+ /* the runtime value of the type on the top of the stack must be
+ * assignment compatible with the type of the array
+ */
+ ENSURE_OPSTACK_SIZE(3);
+
+ if (getOpstackItem(block, 2)->data.class != TINT->data.class) {
+ return verifyError(v, "aastore: array index is not an integer");
+ }
+
+ type = getOpstackItem(block, 1);
+ arrayType = getOpstackItem(block, 3);
+
+ DBG(VERIFY3,
+ dprintf("%sarrayType: ", indent); printType(arrayType);
+ dprintf(" vs. type: "); printType(type);
+ dprintf("\n");
+ );
+
+ if (!isArray(arrayType)) {
+ DBG(VERIFY3, dprintf("%serror: type = ", indent); printType(type); dprintf("\n"); );
+ return verifyError(v, "aastore: top of operand stack is not an array");
+ }
+
+ if (arrayType->tinfo & TINFO_NAME || arrayType->tinfo & TINFO_SIG) {
+ arrayType->tinfo = TINFO_SIG;
+ (arrayType->data.sig)++;
+ }
+ else {
+ if (arrayType->data.class == TOBJARR->data.class) {
+ *arrayType = *TOBJ;
+ } else if (arrayType->data.class != TNULL->data.class) {
+ arrayType->tinfo = TINFO_SIG;
+ arrayType->data.sig = CLASS_CNAME(arrayType->data.class) + 1;
+ }
+ }
+
+ if (!typecheck(v, arrayType, type)) {
+ return verifyError(v, "attempting to store incompatible type in array");
+ }
+
+ opstackPopNBlind(block, 3);
+ break;
+
+#define ARRAY_STORE(_T, _ARRT) \
+ OPSTACK_POP_T(_T); \
+ OPSTACK_POP_T(TINT); \
+ OPSTACK_POP_T(_ARRT);
+
+#define ARRAY_WSTORE(_T, _ARRT) \
+ OPSTACK_WPOP_T(_T); \
+ OPSTACK_POP_T(TINT); \
+ OPSTACK_POP_T(_ARRT);
+
+
+
+
+ case IASTORE: ARRAY_STORE(TINT, TINTARR); break;
+ case FASTORE: ARRAY_STORE(TFLOAT, TFLOATARR); break;
+ case CASTORE: ARRAY_STORE(TINT, TCHARARR); break;
+ case SASTORE: ARRAY_STORE(TINT, TSHORTARR); break;
+
+ case LASTORE: ARRAY_WSTORE(TLONG, TLONGARR); break;
+ case DASTORE: ARRAY_WSTORE(TDOUBLE, TDOUBLEARR); break;
+#undef ARRAY_STORE
+#undef ARRAY_WSTORE
+
+ case BASTORE:
+ /* BASTORE can store either bytes or booleans .... */
+ OPSTACK_POP_T(TINT);
+ OPSTACK_POP_T(TINT);
+
+ if ( !typecheck(v, TBYTEARR, getOpstackTop(block)) &&
+ !typecheck(v, TBOOLARR, getOpstackTop(block))) {
+ DBG(VERIFY3,
+ dprintf(" OPSTACK_TOP: ");
+ printType(getOpstackTop(block));
+ dprintf(" vs. what's we wanted: TBYTEARR or TBOOLARR"); )
+ return verifyError(v, "top of opstack does not have desired type");
+ }
+ opstackPopBlind(block);
+ break;
+
+
+ /**************************************************************
+ * ARITHMETIC INSTRUCTIONS
+ **************************************************************/
+ case IAND: case IOR: case IXOR:
+ case IADD: case ISUB: case IMUL: case IDIV: case IREM:
+ case ISHL: case ISHR: case IUSHR:
+ OPSTACK_POP_T(TINT);
+ break;
+ case INEG:
+ OPSTACK_PEEK_T(TINT);
+ break;
+
+
+ case LAND: case LOR: case LXOR:
+ case LADD: case LSUB: case LMUL: case LDIV: case LREM:
+ OPSTACK_WPOP_T(TLONG);
+ break;
+ case LNEG:
+ OPSTACK_WPEEK_T(TLONG);
+ break;
+
+ case LSHL: case LSHR: case LUSHR:
+ OPSTACK_POP_T(TINT);
+ OPSTACK_WPEEK_T(TLONG);
+ break;
+
+
+ case FADD: case FSUB: case FMUL: case FDIV: case FREM:
+ OPSTACK_POP_T(TFLOAT);
+ break;
+ case FNEG:
+ OPSTACK_PEEK_T(TFLOAT);
+ break;
+
+
+ case DADD: case DSUB: case DDIV: case DMUL: case DREM:
+ OPSTACK_WPOP_T(TDOUBLE);
+ break;
+ case DNEG:
+ OPSTACK_WPEEK_T(TDOUBLE);
+ break;
+
+
+ case LCMP:
+ OPSTACK_WPOP_T(TLONG);
+ OPSTACK_WPOP_T(TLONG);
+ opstackPushBlind(block, TINT);
+ break;
+
+ case FCMPG:
+ case FCMPL:
+ OPSTACK_POP_T(TFLOAT);
+ OPSTACK_POP_T(TFLOAT);
+ opstackPushBlind(block, TINT);
+ break;
+
+ case DCMPG:
+ case DCMPL:
+ OPSTACK_WPOP_T(TDOUBLE);
+ OPSTACK_WPOP_T(TDOUBLE);
+ opstackPushBlind(block, TINT);
+ break;
+
+
+ case IINC:
+ if (wide == true) { GET_WIDX; }
+ else { GET_IDX; }
*** Patch too long, truncated ***
More information about the kaffe
mailing list