⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verify-block.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 3 页
字号:
				type->data.class = CLASS_CLASS(idx, pool);			} else {				const char* namestr;								namestr = CLASS_NAMED(idx, pool);								if (*namestr == '[') {					type->tinfo = TINFO_SIG;					type->data.sig = namestr;				} else {					type->tinfo = TINFO_NAME;					type->data.sig = namestr;				}			}						DBG(VERIFY3,			    dprintf("%s", indent);			    printType(getOpstackTop(block));			    dprintf("\n"); );			break;					case NEW:			GET_WIDX;						CHECK_STACK_OVERFLOW(1);			block->stacksz++;			type = getOpstackTop(block);			if (pool->tags[idx] == CONSTANT_ResolvedClass) {				type->tinfo = TINFO_CLASS;				type->data.class = CLASS_CLASS(idx, pool);			} else {				const char* namestr = CLASS_NAMED(idx, pool);								if (*namestr == '[') {					return verifyError(v, "new: used to create an array");				}								type->tinfo = TINFO_NAME;								type->data.name = namestr;			}						v->uninits = pushUninit(v->uninits, type);			type->tinfo = TINFO_UNINIT;			type->data.uninit  = v->uninits;						DBG(VERIFY3,			    dprintf("%s", indent);			    printType(getOpstackTop(block));			    dprintf("\n"); );			break;								case ANEWARRAY:			GET_WIDX;			OPSTACK_PEEK_T(getTINT());						type = getOpstackTop(block);			if (pool->tags[idx] == CONSTANT_ResolvedClass) {				class = CLASS_CLASS(idx, pool);				type->tinfo = TINFO_CLASS;				type->data.class  = lookupArray(class, v->einfo);								if (type->data.class == NULL) {					return verifyError(v, "anewarray: error creating array type");				}			} else {				char* namestr;								sig = CLASS_NAMED(idx, pool);				if (*sig == '[') {					namestr = checkPtr(gc_malloc(sizeof(char) * (strlen(sig) + 2), KGC_ALLOC_VERIFIER));					v->sigs = pushSig(v->sigs, namestr);					sprintf(namestr, "[%s", sig);				} else {					namestr = checkPtr(gc_malloc(sizeof(char) * (strlen(sig) + 4), KGC_ALLOC_VERIFIER));					v->sigs = pushSig(v->sigs, namestr);					sprintf(namestr, "[L%s;", sig);				}								type->tinfo = TINFO_SIG;				type->data.sig  = namestr;			}						DBG(VERIFY3,			    dprintf("%s", indent);			    printType(getOpstackTop(block));			    dprintf("\n"); );			break;								case GETFIELD:			ENSURE_OPSTACK_SIZE(1);			if (!checkUninit(v->class, getOpstackTop(block))) {				return verifyError(v, "getfield: uninitialized type on top of operand stack");			}						GET_WIDX;			n = FIELDREF_CLASS(idx, pool);						if (pool->tags[n] == CONSTANT_ResolvedClass) {				t->tinfo = TINFO_CLASS;				t->data.class = CLASS_CLASS(n, pool);			} else {				t->tinfo = TINFO_NAME;				t->data.name = CLASS_NAMED(n, pool);			}						OPSTACK_POP_T_BLIND(t);			goto GET_COMMON;					case GETSTATIC:			GET_WIDX;			CHECK_STACK_OVERFLOW(1);		GET_COMMON:			sig = FIELDREF_SIGD(idx, pool);						DBG(VERIFY3, dprintf("%sfield type: %s\n", indent, sig); );						/* TODO: we should just have a function that returns a type based on a signature */			switch (*sig) {			case 'I': case 'Z': case 'S': case 'B': case 'C':				opstackPushBlind(block, getTINT());				break;							case 'F': opstackPushBlind(block, getTFLOAT()); break;			case 'J': OPSTACK_WPUSH(getTLONG()); break;			case 'D': OPSTACK_WPUSH(getTDOUBLE()); break;							case '[':			case 'L':				CHECK_STACK_OVERFLOW(1);				block->stacksz++;				type = getOpstackTop(block);				type->tinfo = TINFO_SIG;				type->data.name = sig;				break;							default:				DBG(VERIFY3, dprintf("%sweird type signature: %s", indent, sig); );				return verifyError(v, "get{field/static}: unrecognized type signature");				break;			}			break;								case PUTFIELD:			if (isWide(getOpstackTop(block))) n = 3;			else                      n = 2;			ENSURE_OPSTACK_SIZE(n);						if (!checkUninit(v->class, getOpstackTop(block))) {				return verifyError(v, "putfield: uninitialized type on top of operand stack");			}						GET_WIDX;			sig = FIELDREF_SIGD(idx, pool);			DBG(VERIFY3, dprintf("                field name::type: %s::%s\n",					     FIELDREF_NAMED(idx, pool), sig); );						switch (*sig) {			case 'I': case 'Z': case 'S': case 'B': case 'C':				OPSTACK_POP_T_BLIND(getTINT());				break;							case 'F': OPSTACK_POP_T_BLIND(getTFLOAT());   break;			case 'J': OPSTACK_WPOP_T_BLIND(getTLONG());   break;			case 'D': OPSTACK_WPOP_T_BLIND(getTDOUBLE()); break;							case '[':			case 'L':				t->tinfo = TINFO_SIG;				t->data.sig = sig;				OPSTACK_POP_T_BLIND(t);				break;							default:				DBG(VERIFY3, dprintf("%sweird type signature: %s", indent, sig); );				return verifyError(v, "put{field/static}: unrecognized type signature");				break;			}									n = FIELDREF_CLASS(idx, pool);			if (pool->tags[n] == CONSTANT_ResolvedClass) {				t->tinfo = TINFO_CLASS;				t->data.class = CLASS_CLASS(n, pool);			} else {				t->tinfo = TINFO_NAME;				t->data.name = CLASS_NAMED(n, pool);			}						OPSTACK_POP_T_BLIND(t);			break;								case PUTSTATIC:			if (getOpstackTop(block) == getTWIDE()) n = 2;			else                      n = 1;			ENSURE_OPSTACK_SIZE(n);						GET_WIDX;			sig = FIELDREF_SIGD(idx, pool);						DBG(VERIFY3, dprintf("                field name::type: %s::%s\n",					     FIELDREF_NAMED(idx, pool), sig); );						switch (*sig) {			case 'I': case 'Z': case 'S': case 'B': case 'C':				OPSTACK_POP_T_BLIND(getTINT());				break;							case 'F': OPSTACK_POP_T_BLIND(getTFLOAT());   break;			case 'J': OPSTACK_WPOP_T_BLIND(getTLONG());   break;			case 'D': OPSTACK_WPOP_T_BLIND(getTDOUBLE()); break;							case '[':			case 'L':				t->tinfo = TINFO_SIG;				t->data.sig = sig;				OPSTACK_POP_T_BLIND(t);				break;							default:				DBG(VERIFY3, dprintf("%sweird type signature: %s", indent, sig); );				return verifyError(v, "put{field/static}: unrecognized type signature");				break;			}			break;									/**************************************************************			 * BRANCHING INSTRUCTIONS...END OF BASIC BLOCKS			 **************************************************************/		case GOTO:		case GOTO_W:			break;					case JSR_W:		case JSR:			CHECK_STACK_OVERFLOW(1);			block->stacksz++;			type = getOpstackTop(block);			type->tinfo = TINFO_ADDR;			type->data.addr = getNextPC(code, pc);			break;		case RET:		        /* type checking done during merging stuff... */			break;					case IF_ACMPEQ:		case IF_ACMPNE:			ENSURE_OPSTACK_SIZE(2);			if (!isReference(getOpstackTop(block)) ||			    !isReference(getOpstackWTop(block))) {				return verifyError(v, "if_acmp* when item on top of stack is not a reference type");			}			opstackPopBlind(block);			opstackPopBlind(block);			break;					case IF_ICMPEQ:		case IF_ICMPNE:		case IF_ICMPGT:		case IF_ICMPGE:		case IF_ICMPLT:		case IF_ICMPLE:			OPSTACK_POP_T(getTINT());		case IFEQ:		case IFNE:		case IFGT:		case IFGE:		case IFLT:		case IFLE:			OPSTACK_POP_T(getTINT());			break;					case IFNONNULL:		case IFNULL:			ENSURE_OPSTACK_SIZE(1);			if (!isReference(getOpstackItem(block, 1))) {				return verifyError(v, "if[non]null: thing on top of stack is not a reference");			}			opstackPopBlind(block);			break;					case LOOKUPSWITCH:		case TABLESWITCH:			OPSTACK_POP_T(getTINT());			return(true);									/**************************************************************			 * METHOD CALLING/RETURNING			 **************************************************************/		case INVOKEVIRTUAL:		case INVOKESPECIAL:		case INVOKEINTERFACE:					case INVOKESTATIC:			if (!checkMethodCall(v, block, pc)) {				DBG(VERIFY3,				    dprintf("\n                some problem with a method call...here's the block:\n");				    printBlock(v->method, block, "                "); );								/* propagate error */				return verifyError(v, "invoke* error");			}			break;								case IRETURN:			OPSTACK_PEEK_T(getTINT());			sig = getMethodReturnSig(v->method);			if (strlen(sig) != 1 || (*sig != 'I' && *sig != 'Z' && *sig != 'S' && *sig != 'B' && *sig != 'C')) {				return verifyError(v, "ireturn: method doesn't return an integer");			}			break;		case FRETURN:			OPSTACK_PEEK_T(getTFLOAT());			sig = getMethodReturnSig(v->method);			if (strcmp(sig, "F")) {				return verifyError(v, "freturn: method doesn't return an float");			}			break;		case LRETURN:			OPSTACK_WPEEK_T(getTLONG());			sig = getMethodReturnSig(v->method);			if (strcmp(sig, "J")) {				return verifyError(v, "lreturn: method doesn't return a long");			}			break;		case DRETURN:			OPSTACK_WPEEK_T(getTDOUBLE());			sig = getMethodReturnSig(v->method);			if (strcmp(sig, "D")) {				return verifyError(v, "dreturn: method doesn't return a double");			}			break;		case RETURN:			sig = getMethodReturnSig(v->method);			if (strcmp(sig, "V")) {				return verifyError(v, "return: must return something in a non-void function");			}			break;		case ARETURN:			ENSURE_OPSTACK_SIZE(1);			t->tinfo = TINFO_SIG;			t->data.sig  = getMethodReturnSig(v->method);			if (!typecheck(v, t, getOpstackTop(block))) {				return verifyError(v, "areturn: top of stack is not type compatible with method return type");			}			break;					case ATHROW:			ENSURE_OPSTACK_SIZE(1);			if (!javaLangThrowable) {			        /* TODO: this is here for now, but perhaps we should have a TTHROWABLE that initialized as				 *       a signature, like we do for String and Object				 */				loadStaticClass(&javaLangThrowable, "java/lang/Throwable");			}			t->tinfo = TINFO_CLASS;			t->data.class = javaLangThrowable;			if (!typecheck(v, t, getOpstackTop(block))) {				DBG(VERIFY3, dprintf("%sATHROW error: ", indent); printType(getOpstackTop(block)); dprintf ("\n"); );				return verifyError(v, "athrow: object on top of stack is not a subclass of throwable");			}						for (n = 0; n < v->method->localsz; n++) {				if (block->locals[n].tinfo & TINFO_UNINIT) {					return verifyError(v, "athrow: uninitialized class instance in a local variable");				}			}			break;									/**************************************************************			 * MISC			 **************************************************************/		case NOP:			break;								case BREAKPOINT:		        /* for internal use only: cannot appear in a class file */			return verifyError(v, "breakpoint instruction cannot appear in classfile");			break;								case MONITORENTER:		case MONITOREXIT:			ENSURE_OPSTACK_SIZE(1);			if(!isReference(getOpstackTop(block))) {				return verifyError(v, "monitor*: top of stack is not an object reference");			}			opstackPopBlind(block);			break;								case DUP:			ENSURE_OPSTACK_SIZE(1);			if (isWide(getOpstackTop(block))) {				return verifyError(v, "dup: on a long or double");			}						OPSTACK_PUSH(getOpstackTop(block));			break;					case DUP_X1:			ENSURE_OPSTACK_SIZE(2);			if (isWide(getOpstackTop(block)) || isWide(getOpstackWTop(block))) {				return verifyError(v, "dup_x1: splits up a double or long");			}						OPSTACK_PUSH(getOpstackTop(block));						*getOpstackItem(block, 2) = *getOpstackItem(block, 3);			*getOpstackItem(block, 3) = *getOpstackItem(block, 1);			break;					case DUP_X2:			ENSURE_OPSTACK_SIZE(3);			if (isWide(getOpstackTop(block))) {				return verifyError(v, "cannot dup_x2 when top item on operand stack is a two byte item");			}						OPSTACK_PUSH(getOpstackTop(block));						*getOpstackItem(block, 2) = *getOpstackItem(block, 3);			*getOpstackItem(block, 3) = *getOpstackItem(block, 4);			*getOpstackItem(block, 4) = *getOpstackItem(block, 1);			break;					case DUP2:			ENSURE_OPSTACK_SIZE(2);						OPSTACK_PUSH(getOpstackWTop(block));			OPSTACK_PUSH(getOpstackWTop(block));			break;					case DUP2_X1:			ENSURE_OPSTACK_SIZE(2);			if (isWide(getOpstackItem(block, 2))) {				return verifyError(v, "dup_x1 requires top 2 bytes on operand stack to be single bytes items");			}			CHECK_STACK_OVERFLOW(2);						opstackPushBlind(block, getOpstackItem(block, 2));			opstackPushBlind(block, getOpstackItem(block, 2));						*getOpstackItem(block, 3) = *getOpstackItem(block, 5);			*getOpstackItem(block, 4) = *getOpstackItem(block, 1);			*getOpstackItem(block, 5) = *getOpstackItem(block, 2);			break;					case DUP2_X2:			ENSURE_OPSTACK_SIZE(4);			if (isWide(getOpstackItem(block, 2)) || isWide(getOpstackItem(block, 4))) {				return verifyError(v, "dup2_x2 where either 2nd or 4th byte is 2nd half of a 2 byte item");			}			CHECK_STACK_OVERFLOW(2);						opstackPushBlind(block, getOpstackItem(block, 2));			opstackPushBlind(block, getOpstackItem(block, 2));						*getOpstackItem(block, 3) = *getOpstackItem(block, 5);			*getOpstackItem(block, 4) = *getOpstackItem(block, 6);			*getOpstackItem(block, 5) = *getOpstackItem(block, 1);			*getOpstackItem(block, 6) = *getOpstackItem(block, 2);			break;								case SWAP:			ENSURE_OPSTACK_SIZE(2);			if (isWide(getOpstackTop(block)) || isWide(getOpstackWTop(block))) {				return verifyError(v, "cannot swap 2 bytes of a long or double");			}						tt         = *getOpstackWTop(block);			*getOpstackWTop(block)  = *getOpstackTop(block);			*getOpstackTop(block) = tt;			break;								case WIDE:			wide = true;			pc = getNextPC(code, pc);			continue;					default:		        /* should never get here because of preprocessing in defineBasicBlocks() */			return verifyError(v, "unknown opcode encountered");		}						pc = getNextPC(code, pc);		if (wide == true) {			wide = false;			pc++;		}	}				/* SUCCESS! */	return(true);		/* take care of the namespace */#undef OPSTACK_POP_N#undef OPSTACK_POP_N_BLIND#undef OPSTACK_WPOP_T#undef OPSTACK_WPOP_T_BLIND#undef OPSTACK_WPOP#undef OPSTACK_POP_T#undef OPSTACK_POP_T_BLIND#undef OPSTACK_POP#undef OPSTACK_WPEEK_T#undef OPSTACK_WPEEK_T_BLIND#undef OPSTACK_PEEK_T#undef OPSTACK_PEEK_T_BLIND#undef OPSTACK_WPUSH#undef OPSTACK_WPUSH_BLIND#undef OPSTACK_PUSH#undef OPSTACK_PUSH_BLIND#undef CHECK_STACK_OVERFLOW#undef ENSURE_OPSTACK_SIZE#undef ENSURE_LOCAL_WTYPE#undef ENSURE_LOCAL_TYPE#undef GET_WIDX#undef GET_IDX}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -