[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