blob: f6cd48ab8d9d2b2b8bea9feaf8a7d8447f5273a8 [file] [log] [blame]
/*
* Copyright (c) 2011 Pekka Enberg
*
* This file is released under the GPL version 2 with the following
* clarification and special exception:
*
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under terms
* of your choice, provided that you also meet, for each linked independent
* module, the terms and conditions of the license of that module. An
* independent module is a module which is not derived from or based on
* this library. If you modify this library, you may extend this exception
* to your version of the library, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
* Please refer to the file LICENSE for details.
*/
#include "vm/interp.h"
#include "cafebabe/code_attribute.h"
#include "vm/method.h"
#include <assert.h>
#include <stdio.h>
enum interp_status {
INTERP_CONTINUE,
INTERP_RETURN,
};
static enum interp_status interp(uint8_t opc)
{
switch (opc) {
case OPC_NOP:
break;
case OPC_ACONST_NULL: assert(!"OPC_ACONST_NULL"); break;
case OPC_ICONST_M1: assert(!"OPC_ICONST_M1"); break;
case OPC_ICONST_0: assert(!"OPC_ICONST_0"); break;
case OPC_ICONST_1: assert(!"OPC_ICONST_1"); break;
case OPC_ICONST_2: assert(!"OPC_ICONST_2"); break;
case OPC_ICONST_3: assert(!"OPC_ICONST_3"); break;
case OPC_ICONST_4: assert(!"OPC_ICONST_4"); break;
case OPC_ICONST_5: assert(!"OPC_ICONST_5"); break;
case OPC_LCONST_0: assert(!"OPC_LCONST_0"); break;
case OPC_LCONST_1: assert(!"OPC_LCONST_1"); break;
case OPC_FCONST_0: assert(!"OPC_FCONST_0"); break;
case OPC_FCONST_1: assert(!"OPC_FCONST_1"); break;
case OPC_FCONST_2: assert(!"OPC_FCONST_2"); break;
case OPC_DCONST_0: assert(!"OPC_DCONST_0"); break;
case OPC_DCONST_1: assert(!"OPC_DCONST_1"); break;
case OPC_BIPUSH: assert(!"OPC_BIPUSH"); break;
case OPC_SIPUSH: assert(!"OPC_SIPUSH"); break;
case OPC_LDC: assert(!"OPC_LDC"); break;
case OPC_LDC_W: assert(!"OPC_LDC_W"); break;
case OPC_LDC2_W: assert(!"OPC_LDC2_W"); break;
case OPC_ILOAD: assert(!"OPC_ILOAD"); break;
case OPC_LLOAD: assert(!"OPC_LLOAD"); break;
case OPC_FLOAD: assert(!"OPC_FLOAD"); break;
case OPC_DLOAD: assert(!"OPC_DLOAD"); break;
case OPC_ALOAD: assert(!"OPC_ALOAD"); break;
case OPC_ILOAD_0: assert(!"OPC_ILOAD_0"); break;
case OPC_ILOAD_1: assert(!"OPC_ILOAD_1"); break;
case OPC_ILOAD_2: assert(!"OPC_ILOAD_2"); break;
case OPC_ILOAD_3: assert(!"OPC_ILOAD_3"); break;
case OPC_LLOAD_0: assert(!"OPC_LLOAD_0"); break;
case OPC_LLOAD_1: assert(!"OPC_LLOAD_1"); break;
case OPC_LLOAD_2: assert(!"OPC_LLOAD_2"); break;
case OPC_LLOAD_3: assert(!"OPC_LLOAD_3"); break;
case OPC_FLOAD_0: assert(!"OPC_FLOAD_0"); break;
case OPC_FLOAD_1: assert(!"OPC_FLOAD_1"); break;
case OPC_FLOAD_2: assert(!"OPC_FLOAD_2"); break;
case OPC_FLOAD_3: assert(!"OPC_FLOAD_3"); break;
case OPC_DLOAD_0: assert(!"OPC_DLOAD_0"); break;
case OPC_DLOAD_1: assert(!"OPC_DLOAD_1"); break;
case OPC_DLOAD_2: assert(!"OPC_DLOAD_2"); break;
case OPC_DLOAD_3: assert(!"OPC_DLOAD_3"); break;
case OPC_ALOAD_0: assert(!"OPC_ALOAD_0"); break;
case OPC_ALOAD_1: assert(!"OPC_ALOAD_1"); break;
case OPC_ALOAD_2: assert(!"OPC_ALOAD_2"); break;
case OPC_ALOAD_3: assert(!"OPC_ALOAD_3"); break;
case OPC_IALOAD: assert(!"OPC_IALOAD"); break;
case OPC_LALOAD: assert(!"OPC_LALOAD"); break;
case OPC_FALOAD: assert(!"OPC_FALOAD"); break;
case OPC_DALOAD: assert(!"OPC_DALOAD"); break;
case OPC_AALOAD: assert(!"OPC_AALOAD"); break;
case OPC_BALOAD: assert(!"OPC_BALOAD"); break;
case OPC_CALOAD: assert(!"OPC_CALOAD"); break;
case OPC_SALOAD: assert(!"OPC_SALOAD"); break;
case OPC_ISTORE: assert(!"OPC_ISTORE"); break;
case OPC_LSTORE: assert(!"OPC_LSTORE"); break;
case OPC_FSTORE: assert(!"OPC_FSTORE"); break;
case OPC_DSTORE: assert(!"OPC_DSTORE"); break;
case OPC_ASTORE: assert(!"OPC_ASTORE"); break;
case OPC_ISTORE_0: assert(!"OPC_ISTORE_0"); break;
case OPC_ISTORE_1: assert(!"OPC_ISTORE_1"); break;
case OPC_ISTORE_2: assert(!"OPC_ISTORE_2"); break;
case OPC_ISTORE_3: assert(!"OPC_ISTORE_3"); break;
case OPC_LSTORE_0: assert(!"OPC_LSTORE_0"); break;
case OPC_LSTORE_1: assert(!"OPC_LSTORE_1"); break;
case OPC_LSTORE_2: assert(!"OPC_LSTORE_2"); break;
case OPC_LSTORE_3: assert(!"OPC_LSTORE_3"); break;
case OPC_FSTORE_0: assert(!"OPC_FSTORE_0"); break;
case OPC_FSTORE_1: assert(!"OPC_FSTORE_1"); break;
case OPC_FSTORE_2: assert(!"OPC_FSTORE_2"); break;
case OPC_FSTORE_3: assert(!"OPC_FSTORE_3"); break;
case OPC_DSTORE_0: assert(!"OPC_DSTORE_0"); break;
case OPC_DSTORE_1: assert(!"OPC_DSTORE_1"); break;
case OPC_DSTORE_2: assert(!"OPC_DSTORE_2"); break;
case OPC_DSTORE_3: assert(!"OPC_DSTORE_3"); break;
case OPC_ASTORE_0: assert(!"OPC_ASTORE_0"); break;
case OPC_ASTORE_1: assert(!"OPC_ASTORE_1"); break;
case OPC_ASTORE_2: assert(!"OPC_ASTORE_2"); break;
case OPC_ASTORE_3: assert(!"OPC_ASTORE_3"); break;
case OPC_IASTORE: assert(!"OPC_IASTORE"); break;
case OPC_LASTORE: assert(!"OPC_LASTORE"); break;
case OPC_FASTORE: assert(!"OPC_FASTORE"); break;
case OPC_DASTORE: assert(!"OPC_DASTORE"); break;
case OPC_AASTORE: assert(!"OPC_AASTORE"); break;
case OPC_BASTORE: assert(!"OPC_BASTORE"); break;
case OPC_CASTORE: assert(!"OPC_CASTORE"); break;
case OPC_SASTORE: assert(!"OPC_SASTORE"); break;
case OPC_POP: assert(!"OPC_POP"); break;
case OPC_POP2: assert(!"OPC_POP2"); break;
case OPC_DUP: assert(!"OPC_DUP"); break;
case OPC_DUP_X1: assert(!"OPC_DUP_X1"); break;
case OPC_DUP_X2: assert(!"OPC_DUP_X2"); break;
case OPC_DUP2: assert(!"OPC_DUP2"); break;
case OPC_DUP2_X1: assert(!"OPC_DUP2_X1"); break;
case OPC_DUP2_X2: assert(!"OPC_DUP2_X2"); break;
case OPC_SWAP: assert(!"OPC_SWAP"); break;
case OPC_IADD: assert(!"OPC_IADD"); break;
case OPC_LADD: assert(!"OPC_LADD"); break;
case OPC_FADD: assert(!"OPC_FADD"); break;
case OPC_DADD: assert(!"OPC_DADD"); break;
case OPC_ISUB: assert(!"OPC_ISUB"); break;
case OPC_LSUB: assert(!"OPC_LSUB"); break;
case OPC_FSUB: assert(!"OPC_FSUB"); break;
case OPC_DSUB: assert(!"OPC_DSUB"); break;
case OPC_IMUL: assert(!"OPC_IMUL"); break;
case OPC_LMUL: assert(!"OPC_LMUL"); break;
case OPC_FMUL: assert(!"OPC_FMUL"); break;
case OPC_DMUL: assert(!"OPC_DMUL"); break;
case OPC_IDIV: assert(!"OPC_IDIV"); break;
case OPC_LDIV: assert(!"OPC_LDIV"); break;
case OPC_FDIV: assert(!"OPC_FDIV"); break;
case OPC_DDIV: assert(!"OPC_DDIV"); break;
case OPC_IREM: assert(!"OPC_IREM"); break;
case OPC_LREM: assert(!"OPC_LREM"); break;
case OPC_FREM: assert(!"OPC_FREM"); break;
case OPC_DREM: assert(!"OPC_DREM"); break;
case OPC_INEG: assert(!"OPC_INEG"); break;
case OPC_LNEG: assert(!"OPC_LNEG"); break;
case OPC_FNEG: assert(!"OPC_FNEG"); break;
case OPC_DNEG: assert(!"OPC_DNEG"); break;
case OPC_ISHL: assert(!"OPC_ISHL"); break;
case OPC_LSHL: assert(!"OPC_LSHL"); break;
case OPC_ISHR: assert(!"OPC_ISHR"); break;
case OPC_LSHR: assert(!"OPC_LSHR"); break;
case OPC_IUSHR: assert(!"OPC_IUSHR"); break;
case OPC_LUSHR: assert(!"OPC_LUSHR"); break;
case OPC_IAND: assert(!"OPC_IAND"); break;
case OPC_LAND: assert(!"OPC_LAND"); break;
case OPC_IOR: assert(!"OPC_IOR"); break;
case OPC_LOR: assert(!"OPC_LOR"); break;
case OPC_IXOR: assert(!"OPC_IXOR"); break;
case OPC_LXOR: assert(!"OPC_LXOR"); break;
case OPC_IINC: assert(!"OPC_IINC"); break;
case OPC_I2L: assert(!"OPC_I2L"); break;
case OPC_I2F: assert(!"OPC_I2F"); break;
case OPC_I2D: assert(!"OPC_I2D"); break;
case OPC_L2I: assert(!"OPC_L2I"); break;
case OPC_L2F: assert(!"OPC_L2F"); break;
case OPC_L2D: assert(!"OPC_L2D"); break;
case OPC_F2I: assert(!"OPC_F2I"); break;
case OPC_F2L: assert(!"OPC_F2L"); break;
case OPC_F2D: assert(!"OPC_F2D"); break;
case OPC_D2I: assert(!"OPC_D2I"); break;
case OPC_D2L: assert(!"OPC_D2L"); break;
case OPC_D2F: assert(!"OPC_D2F"); break;
case OPC_I2B: assert(!"OPC_I2B"); break;
case OPC_I2C: assert(!"OPC_I2C"); break;
case OPC_I2S: assert(!"OPC_I2S"); break;
case OPC_LCMP: assert(!"OPC_LCMP"); break;
case OPC_FCMPL: assert(!"OPC_FCMPL"); break;
case OPC_FCMPG: assert(!"OPC_FCMPG"); break;
case OPC_DCMPL: assert(!"OPC_DCMPL"); break;
case OPC_DCMPG: assert(!"OPC_DCMPG"); break;
case OPC_IFEQ: assert(!"OPC_IFEQ"); break;
case OPC_IFNE: assert(!"OPC_IFNE"); break;
case OPC_IFLT: assert(!"OPC_IFLT"); break;
case OPC_IFGE: assert(!"OPC_IFGE"); break;
case OPC_IFGT: assert(!"OPC_IFGT"); break;
case OPC_IFLE: assert(!"OPC_IFLE"); break;
case OPC_IF_ICMPEQ: assert(!"OPC_IF_ICMPEQ"); break;
case OPC_IF_ICMPNE: assert(!"OPC_IF_ICMPNE"); break;
case OPC_IF_ICMPLT: assert(!"OPC_IF_ICMPLT"); break;
case OPC_IF_ICMPGE: assert(!"OPC_IF_ICMPGE"); break;
case OPC_IF_ICMPGT: assert(!"OPC_IF_ICMPGT"); break;
case OPC_IF_ICMPLE: assert(!"OPC_IF_ICMPLE"); break;
case OPC_IF_ACMPEQ: assert(!"OPC_IF_ACMPEQ"); break;
case OPC_IF_ACMPNE: assert(!"OPC_IF_ACMPNE"); break;
case OPC_GOTO: assert(!"OPC_GOTO"); break;
case OPC_JSR: assert(!"OPC_JSR"); break;
case OPC_RET: assert(!"OPC_RET"); break;
case OPC_TABLESWITCH: assert(!"OPC_TABLESWITCH"); break;
case OPC_LOOKUPSWITCH: assert(!"OPC_LOOKUPSWITCH"); break;
case OPC_IRETURN: assert(!"OPC_IRETURN"); break;
case OPC_LRETURN: assert(!"OPC_LRETURN"); break;
case OPC_FRETURN: assert(!"OPC_FRETURN"); break;
case OPC_DRETURN: assert(!"OPC_DRETURN"); break;
case OPC_ARETURN: assert(!"OPC_ARETURN"); break;
case OPC_RETURN:
return INTERP_RETURN;
case OPC_GETSTATIC: assert(!"OPC_GETSTATIC"); break;
case OPC_PUTSTATIC: assert(!"OPC_PUTSTATIC"); break;
case OPC_GETFIELD: assert(!"OPC_GETFIELD"); break;
case OPC_PUTFIELD: assert(!"OPC_PUTFIELD"); break;
case OPC_INVOKEVIRTUAL: assert(!"OPC_INVOKEVIRTUAL"); break;
case OPC_INVOKESPECIAL: assert(!"OPC_INVOKESPECIAL"); break;
case OPC_INVOKESTATIC: assert(!"OPC_INVOKESTATIC"); break;
case OPC_INVOKEINTERFACE: assert(!"OPC_INVOKEINTERFACE"); break;
case OPC_NEW: assert(!"OPC_NEW"); break;
case OPC_NEWARRAY: assert(!"OPC_NEWARRAY"); break;
case OPC_ANEWARRAY: assert(!"OPC_ANEWARRAY"); break;
case OPC_ARRAYLENGTH: assert(!"OPC_ARRAYLENGTH"); break;
case OPC_ATHROW: assert(!"OPC_ATHROW"); break;
case OPC_CHECKCAST: assert(!"OPC_CHECKCAST"); break;
case OPC_INSTANCEOF: assert(!"OPC_INSTANCEOF"); break;
case OPC_MONITORENTER: assert(!"OPC_MONITORENTER"); break;
case OPC_MONITOREXIT: assert(!"OPC_MONITOREXIT"); break;
case OPC_WIDE: assert(!"OPC_WIDE"); break;
case OPC_MULTIANEWARRAY: assert(!"OPC_MULTIANEWARRAY"); break;
case OPC_IFNULL: assert(!"OPC_IFNULL"); break;
case OPC_IFNONNULL: assert(!"OPC_IFNONNULL"); break;
case OPC_GOTO_W: assert(!"OPC_GOTO_W"); break;
case OPC_JSR_W: assert(!"OPC_JSR_W"); break;
case OPC_BREAKPOINT: assert(!"OPC_BREAKPOINT"); break;
default:
assert(!"unknown bytecode");
}
return INTERP_CONTINUE;
}
void vm_interp_method_v(struct vm_method *method, va_list args, union jvalue *result)
{
uint32_t pc;
pc = 0;
while (pc < method->code_attribute.code_length) {
uint8_t opc = method->code_attribute.code[pc];
if (interp(opc) == INTERP_RETURN)
return;
pc++;
}
}