Use new BytecodeInfo (much simpler)

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@451 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 93ce417a9b
commit 94da811de1
  1. 489
      jode/jode/decompiler/Opcodes.java

@ -48,201 +48,64 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
}; };
private static StructuredBlock createNormal(CodeAnalyzer ca, private static StructuredBlock createNormal(CodeAnalyzer ca,
int addr, int length, Instruction instr,
Expression instr) Expression expr)
{ {
return new InstructionBlock(instr, new Jump(addr+length)); return new InstructionBlock(expr, new Jump(FlowBlock.NEXT_BY_ADDR));
} }
private static StructuredBlock createSpecial(CodeAnalyzer ca, private static StructuredBlock createSpecial(CodeAnalyzer ca,
int addr, int length, Instruction instr,
int type, int stackcount, int param) int type,
int stackcount, int param)
{ {
return new SpecialBlock(type, stackcount, param, return new SpecialBlock(type, stackcount, param,
new Jump(addr+length)); new Jump(FlowBlock.NEXT_BY_ADDR));
} }
private static StructuredBlock createGoto(CodeAnalyzer ca, private static StructuredBlock createGoto(CodeAnalyzer ca,
int addr, int length, int destAddr) Instruction instr)
{ {
return new EmptyBlock(new Jump(destAddr)); return new EmptyBlock(new Jump((FlowBlock)instr.succs[0].tmpInfo));
} }
private static StructuredBlock createJsr(CodeAnalyzer ca, private static StructuredBlock createJsr(CodeAnalyzer ca,
int addr, int length, Instruction instr)
int destAddr)
{ {
return new JsrBlock(new Jump(addr+length), return new JsrBlock(new Jump((FlowBlock)instr.succs[0].tmpInfo),
new Jump(destAddr)); new Jump(FlowBlock.NEXT_BY_ADDR));
} }
private static StructuredBlock createIfGoto(CodeAnalyzer ca, private static StructuredBlock createIfGoto(CodeAnalyzer ca,
int addr, int length, Instruction instr,
int destAddr, Expression instr) Expression expr)
{ {
return new ConditionalBlock(instr, return new ConditionalBlock
new Jump(destAddr), (expr, new Jump((FlowBlock)instr.succs[0].tmpInfo),
new Jump(addr+length)); new Jump(FlowBlock.NEXT_BY_ADDR));
} }
private static StructuredBlock createSwitch(CodeAnalyzer ca, private static StructuredBlock createSwitch(CodeAnalyzer ca,
int addr, int length, Instruction instr,
int[] cases, int[] dests) int[] cases, FlowBlock[] dests)
{ {
return new SwitchBlock(new NopOperator(Type.tUInt), cases, dests); return new SwitchBlock(new NopOperator(Type.tUInt), cases, dests);
} }
private static StructuredBlock createBlock(CodeAnalyzer ca, private static StructuredBlock createBlock(CodeAnalyzer ca,
int addr, int length, Instruction instr,
StructuredBlock block) StructuredBlock block)
{ {
return block; return block;
} }
private static StructuredBlock createRet(CodeAnalyzer ca, private static StructuredBlock createRet(CodeAnalyzer ca,
int addr, int length, Instruction instr,
LocalInfo local) LocalInfo local)
{ {
return new RetBlock(local); return new RetBlock(local);
} }
/**
* Skips the specified number of bytes in the input stream. This calls
* skip as long until the bytes are all skipped.
* @param is the inputstream to skip.
* @param count the number of bytes to skip.
*/
private final static void skip(InputStream is, long count)
throws IOException {
while (count > 0) {
long skipped = is.skip(count);
if (skipped == 0)
throw new EOFException("Can't skip");
count -= skipped;
}
}
/**
* Read an opcode out of a data input stream and determine its size
* and its successors.
* @param addr The current address.
* @param stream The stream containing the java byte code.
* @return An array of ints; the first entry is the size of the
* instruction, the remaining are the successors.
*/
public static int[] getSizeAndSuccs(int addr, DataInputStream stream)
throws IOException
{
int opcode = stream.readUnsignedByte();
switch (opcode) {
case opc_multianewarray:
skip(stream, 3);
return new int[] { 4, addr+4 };
case opc_invokeinterface:
skip(stream, 4);
return new int[] { 5, addr+5 };
case opc_wide: {
switch (opcode = stream.readUnsignedByte()) {
case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload:
case opc_istore: case opc_lstore:
case opc_fstore: case opc_dstore: case opc_astore:
skip(stream, 2);
return new int[] { 4, addr+4 };
case opc_iinc:
skip(stream, 4);
return new int[] { 6, addr+6 };
case opc_ret:
skip(stream, 2);
return new int[] { 4 };
default:
throw new ClassFormatError("Invalid wide opcode "+opcode);
}
}
case opc_ret:
skip(stream, 1);
return new int[] { 2 };
case opc_jsr_w:
return new int[] { 5, addr + 5, addr + stream.readInt() };
case opc_goto:
return new int[] { 3, addr + stream.readShort() };
case opc_goto_w:
return new int[] { 5, addr + stream.readInt() };
case opc_tableswitch: {
int length = 3-(addr % 4);
skip(stream, length);
int def = addr + stream.readInt();
int low = stream.readInt();
int high = stream.readInt();
int[] dests = new int[high-low+3];
for (int i=0; i+low <= high; i++) {
dests[i+1] = addr + stream.readInt();
}
dests[dests.length-1] = def;
dests[0] = length + 13 + 4 * (high-low+1);
return dests;
}
case opc_lookupswitch: {
int length = 3-(addr % 4);
skip(stream, length);
int def = addr + stream.readInt();
int npairs = stream.readInt();
int[] dests = new int[npairs+2];
for (int i=0; i < npairs; i++) {
int value = stream.readInt();
dests[i+1] = addr + stream.readInt();
}
dests[npairs+1] = def;
dests[0] = length + 9 + 8 * npairs;
return dests;
}
case opc_ifnull: case opc_ifnonnull:
case opc_jsr:
return new int[] { 3, addr + 3, addr + stream.readShort() };
case opc_sipush:
case opc_ldc_w:
case opc_ldc2_w:
case opc_iinc:
case opc_getstatic:
case opc_getfield:
case opc_putstatic:
case opc_putfield:
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic:
case opc_new:
case opc_anewarray:
case opc_checkcast:
case opc_instanceof:
skip(stream, 2);
return new int[] { 3, addr+3 };
}
if (opcode == opc_newarray
|| (opcode >= opc_bipush && opcode <= opc_aload)
|| (opcode >= opc_istore && opcode <= opc_astore)) {
skip(stream, 1);
return new int[] { 2, addr+2 };
}
if (opcode == opc_athrow
|| opcode >= opc_ireturn && opcode <= opc_return)
return new int[] { 1 };
if (opcode >= opc_ifeq && opcode <= opc_if_acmpne)
return new int[] { 3, addr + 3, addr + stream.readShort() };
if (opcode == opc_xxxunusedxxx || opcode > opc_breakpoint)
throw new ClassFormatError("Invalid opcode "+opcode);
return new int[] { 1, addr+1 };
}
/** /**
* Read an opcode out of a data input stream containing the bytecode. * Read an opcode out of a data input stream containing the bytecode.
* @param addr The current address. * @param addr The current address.
@ -254,163 +117,104 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
* @exception IOException if an read error occured. * @exception IOException if an read error occured.
* @exception ClassFormatError if an invalid opcode is detected. * @exception ClassFormatError if an invalid opcode is detected.
*/ */
public static StructuredBlock readOpcode(ConstantPool cpool, public static StructuredBlock readOpcode(Instruction instr,
int addr, DataInputStream stream, CodeAnalyzer ca)
CodeAnalyzer ca) throws ClassFormatError
throws IOException, ClassFormatError
{ {
int opcode = stream.readUnsignedByte(); int opcode = instr.opcode;
switch (opcode) { switch (opcode) {
case opc_nop: case opc_nop:
return createBlock return createBlock(ca, instr, new EmptyBlock
(ca, addr, 1, new EmptyBlock(new Jump(addr+1))); (new Jump(FlowBlock.NEXT_BY_ADDR)));
case opc_aconst_null: case opc_aconst_null:
return createNormal
(ca, addr, 1, new ConstOperator(Type.tUObject, "null"));
case opc_iconst_m1: case opc_iconst_m1:
case opc_iconst_0: case opc_iconst_1: case opc_iconst_2: case opc_iconst_0: case opc_iconst_1: case opc_iconst_2:
case opc_iconst_3: case opc_iconst_4: case opc_iconst_5: case opc_iconst_3: case opc_iconst_4: case opc_iconst_5:
return createNormal
(ca, addr, 1, new ConstOperator(opcode - opc_iconst_0));
case opc_lconst_0: case opc_lconst_1: case opc_lconst_0: case opc_lconst_1:
return createNormal
(ca, addr, 1, new ConstOperator
(Type.tLong, (char) (opcode + ('0'-opc_lconst_0)) + ""));
case opc_fconst_0: case opc_fconst_1: case opc_fconst_2: case opc_fconst_0: case opc_fconst_1: case opc_fconst_2:
return createNormal
(ca, addr, 1, new ConstOperator
(Type.tFloat, (char) (opcode + ('0'-opc_fconst_0)) + ".0"));
case opc_dconst_0: case opc_dconst_1: case opc_dconst_0: case opc_dconst_1:
return createNormal
(ca, addr, 1, new ConstOperator
(Type.tDouble, (char) (opcode + ('0'-opc_dconst_0)) + ".0"));
case opc_bipush: case opc_bipush:
return createNormal
(ca, addr, 2, new ConstOperator(stream.readByte()));
case opc_sipush: case opc_sipush:
return createNormal case opc_ldc:
(ca, addr, 3, new ConstOperator(stream.readShort()));
case opc_ldc: {
int index = stream.readUnsignedByte();
ConstOperator op;
if (cpool.getConstantType(index) == Type.tInt)
op = new ConstOperator(cpool.getConstantInt(index));
else
op = new ConstOperator(cpool.getConstantType(index),
cpool.getConstantString(index));
return createNormal (ca, addr, 2, op);
}
case opc_ldc_w: case opc_ldc_w:
case opc_ldc2_w: { case opc_ldc2_w:
int index = stream.readUnsignedShort(); return createNormal (ca, instr, new ConstOperator(instr.objData));
ConstOperator op;
if (cpool.getConstantType(index) == Type.tInt)
op = new ConstOperator(cpool.getConstantInt(index));
else
op = new ConstOperator(cpool.getConstantType(index),
cpool.getConstantString(index));
return createNormal(ca, addr, 3, op);
}
case opc_iload: case opc_lload: case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload: case opc_fload: case opc_dload: case opc_aload:
return createNormal return createNormal
(ca, addr, 2, new LocalLoadOperator (ca, instr, new LocalLoadOperator
(types[0][opcode-opc_iload], (types[0][opcode-opc_iload],
ca.getLocalInfo(addr, stream.readUnsignedByte()))); ca.getLocalInfo(instr.addr, instr.localSlot)));
case opc_iload_0: case opc_iload_1: case opc_iload_2: case opc_iload_3:
case opc_lload_0: case opc_lload_1: case opc_lload_2: case opc_lload_3:
case opc_fload_0: case opc_fload_1: case opc_fload_2: case opc_fload_3:
case opc_dload_0: case opc_dload_1: case opc_dload_2: case opc_dload_3:
case opc_aload_0: case opc_aload_1: case opc_aload_2: case opc_aload_3:
return createNormal
(ca, addr, 1, new LocalLoadOperator
(types[0][(opcode-opc_iload_0)/4],
ca.getLocalInfo(addr, (opcode-opc_iload_0) & 3)));
case opc_iaload: case opc_laload: case opc_iaload: case opc_laload:
case opc_faload: case opc_daload: case opc_aaload: case opc_faload: case opc_daload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload: case opc_baload: case opc_caload: case opc_saload:
return createNormal return createNormal
(ca, addr, 1, new ArrayLoadOperator (ca, instr, new ArrayLoadOperator
(types[1][opcode - opc_iaload])); (types[1][opcode - opc_iaload]));
case opc_istore: case opc_lstore: case opc_istore: case opc_lstore:
case opc_fstore: case opc_dstore: case opc_astore: case opc_fstore: case opc_dstore: case opc_astore:
return createNormal return createNormal
(ca, addr, 2, new LocalStoreOperator (ca, instr, new LocalStoreOperator
(types[0][opcode-opc_istore], (types[0][opcode-opc_istore],
ca.getLocalInfo(addr+2, stream.readUnsignedByte()), ca.getLocalInfo(instr.addr+2, instr.localSlot),
Operator.ASSIGN_OP));
case opc_istore_0: case opc_istore_1:
case opc_istore_2: case opc_istore_3:
case opc_lstore_0: case opc_lstore_1:
case opc_lstore_2: case opc_lstore_3:
case opc_fstore_0: case opc_fstore_1:
case opc_fstore_2: case opc_fstore_3:
case opc_dstore_0: case opc_dstore_1:
case opc_dstore_2: case opc_dstore_3:
case opc_astore_0: case opc_astore_1:
case opc_astore_2: case opc_astore_3:
return createNormal
(ca, addr, 1, new LocalStoreOperator
(types[0][(opcode-opc_istore_0)/4],
ca.getLocalInfo(addr+1, (opcode-opc_istore_0) & 3),
Operator.ASSIGN_OP)); Operator.ASSIGN_OP));
case opc_iastore: case opc_lastore: case opc_iastore: case opc_lastore:
case opc_fastore: case opc_dastore: case opc_aastore: case opc_fastore: case opc_dastore: case opc_aastore:
case opc_bastore: case opc_castore: case opc_sastore: case opc_bastore: case opc_castore: case opc_sastore:
return createNormal return createNormal
(ca, addr, 1, new ArrayStoreOperator (ca, instr, new ArrayStoreOperator
(types[1][opcode - opc_iastore])); (types[1][opcode - opc_iastore]));
case opc_pop: case opc_pop2: case opc_pop: case opc_pop2:
return createSpecial return createSpecial
(ca, addr, 1, SpecialBlock.POP, opcode - opc_pop + 1, 0); (ca, instr, SpecialBlock.POP, opcode - opc_pop + 1, 0);
case opc_dup: case opc_dup_x1: case opc_dup_x2: case opc_dup: case opc_dup_x1: case opc_dup_x2:
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: case opc_dup2: case opc_dup2_x1: case opc_dup2_x2:
return createSpecial return createSpecial
(ca, addr, 1, SpecialBlock.DUP, (ca, instr, SpecialBlock.DUP,
(opcode - opc_dup)/3+1, (opcode - opc_dup)%3); (opcode - opc_dup)/3+1, (opcode - opc_dup)%3);
case opc_swap: case opc_swap:
return createSpecial(ca, addr, 1, SpecialBlock.SWAP, 1, 0); return createSpecial(ca, instr, SpecialBlock.SWAP, 1, 0);
case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd:
case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub:
case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul:
case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv:
case opc_irem: case opc_lrem: case opc_frem: case opc_drem: case opc_irem: case opc_lrem: case opc_frem: case opc_drem:
return createNormal return createNormal
(ca, addr, 1, new BinaryOperator (ca, instr, new BinaryOperator
(types[3][(opcode - opc_iadd)%4], (types[3][(opcode - opc_iadd)%4],
(opcode - opc_iadd)/4+Operator.ADD_OP)); (opcode - opc_iadd)/4+Operator.ADD_OP));
case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg:
return createNormal return createNormal
(ca, addr, 1, new UnaryOperator (ca, instr, new UnaryOperator
(types[3][opcode - opc_ineg], Operator.NEG_OP)); (types[3][opcode - opc_ineg], Operator.NEG_OP));
case opc_ishl: case opc_lshl: case opc_ishl: case opc_lshl:
case opc_ishr: case opc_lshr: case opc_ishr: case opc_lshr:
case opc_iushr: case opc_lushr: case opc_iushr: case opc_lushr:
return createNormal return createNormal
(ca, addr, 1, new ShiftOperator (ca, instr, new ShiftOperator
(types[3][(opcode - opc_ishl)%2], (types[3][(opcode - opc_ishl)%2],
(opcode - opc_ishl)/2 + Operator.SHIFT_OP)); (opcode - opc_ishl)/2 + Operator.SHIFT_OP));
case opc_iand: case opc_land: case opc_iand: case opc_land:
case opc_ior : case opc_lor : case opc_ior : case opc_lor :
case opc_ixor: case opc_lxor: case opc_ixor: case opc_lxor:
return createNormal return createNormal
(ca, addr, 1, new BinaryOperator (ca, instr, new BinaryOperator
(types[4][(opcode - opc_iand)%2], (types[4][(opcode - opc_iand)%2],
(opcode - opc_iand)/2 + Operator.AND_OP)); (opcode - opc_iand)/2 + Operator.AND_OP));
case opc_iinc: { case opc_iinc: {
int local = stream.readUnsignedByte(); int value = instr.intData;
int value = stream.readByte();
int operation = Operator.ADD_OP; int operation = Operator.ADD_OP;
if (value < 0) { if (value < 0) {
value = -value; value = -value;
operation = Operator.NEG_OP; operation = Operator.NEG_OP;
} }
LocalInfo li = ca.getLocalInfo(addr, local); LocalInfo li = ca.getLocalInfo(instr.addr, instr.localSlot);
li.setType(Type.tUInt); li.setType(Type.tUInt);
return createNormal return createNormal
(ca, addr, 3, new IIncOperator (ca, instr, new IIncOperator
(li, Integer.toString(value), (li, Integer.toString(value),
operation + Operator.OPASSIGN_OP)); operation + Operator.OPASSIGN_OP));
} }
case opc_i2l: case opc_i2f: case opc_i2d: case opc_i2l: case opc_i2f: case opc_i2d:
case opc_l2i: case opc_l2f: case opc_l2d: case opc_l2i: case opc_l2f: case opc_l2d:
@ -421,115 +225,97 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
if (to >= from) if (to >= from)
to++; to++;
return createNormal return createNormal
(ca, addr, 1, new ConvertOperator(types[3][from], (ca, instr, new ConvertOperator(types[3][from],
types[3][to])); types[3][to]));
} }
case opc_i2b: case opc_i2c: case opc_i2s: case opc_i2b: case opc_i2c: case opc_i2s:
return createNormal return createNormal
(ca, addr, 1, new ConvertOperator (ca, instr, new ConvertOperator
(types[3][0], types[2][opcode-opc_i2b])); (types[3][0], types[2][opcode-opc_i2b]));
case opc_lcmp: case opc_lcmp:
case opc_fcmpl: case opc_fcmpg: case opc_fcmpl: case opc_fcmpg:
case opc_dcmpl: case opc_dcmpg: case opc_dcmpl: case opc_dcmpg:
return createNormal return createNormal
(ca, addr, 1, new CompareToIntOperator (ca, instr, new CompareToIntOperator
(types[3][(opcode-(opc_lcmp-3))/2], (types[3][(opcode-(opc_lcmp-3))/2],
(opcode-(opc_lcmp-3))%2)); (opcode-(opc_lcmp-3))%2));
case opc_ifeq: case opc_ifne: case opc_ifeq: case opc_ifne:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, instr,
new CompareUnaryOperator new CompareUnaryOperator
(Type.tBoolUInt, opcode - (opc_ifeq-Operator.COMPARE_OP))); (Type.tBoolUInt, opcode - (opc_ifeq-Operator.COMPARE_OP)));
case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle: case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, instr,
new CompareUnaryOperator new CompareUnaryOperator
(Type.tUInt, opcode - (opc_ifeq-Operator.COMPARE_OP))); (Type.tUInt, opcode - (opc_ifeq-Operator.COMPARE_OP)));
case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpeq: case opc_if_icmpne:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, instr,
new CompareBinaryOperator new CompareBinaryOperator
(Type.tBoolInt, (Type.tBoolInt,
opcode - (opc_if_icmpeq-Operator.COMPARE_OP))); opcode - (opc_if_icmpeq-Operator.COMPARE_OP)));
case opc_if_icmplt: case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmpge:
case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmpgt: case opc_if_icmple:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, instr,
new CompareBinaryOperator new CompareBinaryOperator
(Type.tUInt, (Type.tUInt,
opcode - (opc_if_icmpeq-Operator.COMPARE_OP))); opcode - (opc_if_icmpeq-Operator.COMPARE_OP)));
case opc_if_acmpeq: case opc_if_acmpne: case opc_if_acmpeq: case opc_if_acmpne:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, instr,
new CompareBinaryOperator new CompareBinaryOperator
(Type.tUObject, (Type.tUObject,
opcode - (opc_if_acmpeq-Operator.COMPARE_OP))); opcode - (opc_if_acmpeq-Operator.COMPARE_OP)));
case opc_goto: case opc_goto:
return createGoto return createGoto(ca, instr);
(ca, addr, 3, addr+stream.readShort());
case opc_jsr: case opc_jsr:
return createJsr return createJsr(ca, instr);
(ca, addr, 3, addr+stream.readShort());
case opc_ret: case opc_ret:
return createRet return createRet
(ca, addr, 2, (ca, instr, ca.getLocalInfo(instr.addr, instr.localSlot));
ca.getLocalInfo(addr, stream.readUnsignedByte()));
case opc_tableswitch: { case opc_tableswitch: {
int length = 3-(addr % 4); int low = instr.intData;
skip(stream, length); int[] cases = new int[instr.succs.length-1];
int def = addr + stream.readInt(); FlowBlock[] dests = new FlowBlock[instr.succs.length];
int low = stream.readInt(); for (int i=0; i < cases.length; i++) {
int high = stream.readInt();
int[] cases = new int[high-low+1];
int[] dests = new int[high-low+2];
for (int i=0; i+low <= high; i++) {
cases[i] = i+low; cases[i] = i+low;
dests[i] = addr + stream.readInt(); dests[i] = (FlowBlock) instr.succs[i+1].tmpInfo;
}
dests[cases.length] = def;
length += 13 + 4 * cases.length;
return createSwitch
(ca, addr, length, cases, dests);
} }
dests[cases.length] = (FlowBlock) instr.succs[0].tmpInfo;
return createSwitch(ca, instr, cases, dests);
}
case opc_lookupswitch: { case opc_lookupswitch: {
int length = 3-(addr % 4); int[] cases = (int[]) instr.objData;
skip(stream, length); FlowBlock[] dests = new FlowBlock[instr.succs.length];
int def = addr + stream.readInt(); for (int i=0; i < dests.length; i++)
int npairs = stream.readInt(); dests[i] = (FlowBlock) instr.succs[i].tmpInfo;
int[] cases = new int[npairs]; dests[cases.length] = (FlowBlock) instr.succs[0].tmpInfo;
int[] dests = new int[npairs+1]; return createSwitch(ca, instr, cases, dests);
for (int i=0; i < npairs; i++) {
cases[i] = stream.readInt();
dests[i] = addr + stream.readInt();
}
dests[npairs] = def;
length += 9 + 8 * npairs;
return createSwitch
(ca, addr, length, cases, dests);
} }
case opc_ireturn: case opc_lreturn: case opc_ireturn: case opc_lreturn:
case opc_freturn: case opc_dreturn: case opc_areturn: { case opc_freturn: case opc_dreturn: case opc_areturn: {
/* Address -1 is interpreted as end of method */
Type retType = Type.tSubType(ca.getMethod().getReturnType()); Type retType = Type.tSubType(ca.getMethod().getReturnType());
return createBlock return createBlock
(ca, addr, 1, new ReturnBlock(new NopOperator(retType))); (ca, instr, new ReturnBlock(new NopOperator(retType)));
} }
case opc_return: case opc_return:
return createBlock return createBlock
(ca, addr, 1, new EmptyBlock(new Jump(-1))); (ca, instr, new EmptyBlock(new Jump(FlowBlock.END_OF_METHOD)));
case opc_getstatic: case opc_getstatic:
case opc_getfield: { case opc_getfield: {
String[] ref = cpool.getRef(stream.readUnsignedShort()); String[] ref = (String[]) instr.objData;
return createNormal return createNormal
(ca, addr, 3, new GetFieldOperator (ca, instr, new GetFieldOperator
(ca, opcode == opc_getstatic, (ca, opcode == opc_getstatic,
Type.tClass(ref[0]), Type.tType(ref[2]), ref[1])); Type.tClass(ref[0]), Type.tType(ref[2]), ref[1]));
} }
case opc_putstatic: case opc_putstatic:
case opc_putfield: { case opc_putfield: {
String[] ref = cpool.getRef(stream.readUnsignedShort()); String[] ref = (String[]) instr.objData;
return createNormal return createNormal
(ca, addr, 3, new PutFieldOperator (ca, instr, new PutFieldOperator
(ca, opcode == opc_putstatic, (ca, opcode == opc_putstatic,
Type.tClass(ref[0]), Type.tType(ref[2]), ref[1])); Type.tClass(ref[0]), Type.tType(ref[2]), ref[1]));
} }
@ -537,27 +323,21 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
case opc_invokespecial: case opc_invokespecial:
case opc_invokestatic : case opc_invokestatic :
case opc_invokeinterface: { case opc_invokeinterface: {
String[] ref = cpool.getRef(stream.readUnsignedShort()); String[] ref = (String[]) instr.objData;
StructuredBlock block = createNormal StructuredBlock block = createNormal
(ca, addr, opcode == opc_invokeinterface ? 5 : 3, (ca, instr, new InvokeOperator
new InvokeOperator (ca, opcode == opc_invokespecial, Type.tClass(ref[0]),
(ca, opcode == opc_invokespecial, new MethodType(opcode == opc_invokestatic, ref[2]), ref[1]));
Type.tClass(ref[0]),
new MethodType(opcode == opc_invokestatic, ref[2]),
ref[1]));
if (opcode == opc_invokeinterface)
stream.readUnsignedShort();
return block; return block;
} }
case opc_new: { case opc_new: {
Type type = Type.tClassOrArray Type type = Type.tClassOrArray((String) instr.objData);
(cpool.getClassName(stream.readUnsignedShort()));
type.useType(); type.useType();
return createNormal(ca, addr, 3, new NewOperator(type)); return createNormal(ca, instr, new NewOperator(type));
} }
case opc_newarray: { case opc_newarray: {
Type type; Type type;
switch (stream.readUnsignedByte()) { switch (instr.intData) {
case 4: type = Type.tBoolean; break; case 4: type = Type.tBoolean; break;
case 5: type = Type.tChar ; break; case 5: type = Type.tChar ; break;
case 6: type = Type.tFloat ; break; case 6: type = Type.tFloat ; break;
@ -571,103 +351,52 @@ public abstract class Opcodes implements jode.bytecode.Opcodes {
} }
type.useType(); type.useType();
return createNormal return createNormal
(ca, addr, 2, new NewArrayOperator(Type.tArray(type), 1)); (ca, instr, new NewArrayOperator(Type.tArray(type), 1));
} }
case opc_anewarray: { case opc_anewarray: {
Type type = Type.tClassOrArray Type type = Type.tClassOrArray((String) instr.objData);
(cpool.getClassName(stream.readUnsignedShort()));
type.useType(); type.useType();
return createNormal return createNormal
(ca, addr, 3, new NewArrayOperator(Type.tArray(type), 1)); (ca, instr, new NewArrayOperator(Type.tArray(type), 1));
} }
case opc_arraylength: case opc_arraylength:
return createNormal return createNormal
(ca, addr, 1, new ArrayLengthOperator()); (ca, instr, new ArrayLengthOperator());
case opc_athrow: case opc_athrow:
return createBlock return createBlock
(ca, addr, 1, (ca, instr,
new ThrowBlock(new NopOperator(Type.tUObject))); new ThrowBlock(new NopOperator(Type.tUObject)));
case opc_checkcast: { case opc_checkcast: {
Type type = Type.tClassOrArray Type type = Type.tClassOrArray((String) instr.objData);
(cpool.getClassName(stream.readUnsignedShort()));
type.useType(); type.useType();
return createNormal return createNormal
(ca, addr, 3, new CheckCastOperator(type)); (ca, instr, new CheckCastOperator(type));
} }
case opc_instanceof: { case opc_instanceof: {
Type type = Type.tClassOrArray Type type = Type.tClassOrArray((String) instr.objData);
(cpool.getClassName(stream.readUnsignedShort()));
type.useType(); type.useType();
return createNormal return createNormal
(ca, addr, 3, new InstanceOfOperator(type)); (ca, instr, new InstanceOfOperator(type));
} }
case opc_monitorenter: case opc_monitorenter:
return createNormal(ca, addr, 1, return createNormal(ca, instr,
new MonitorEnterOperator()); new MonitorEnterOperator());
case opc_monitorexit: case opc_monitorexit:
return createNormal(ca, addr, 1, return createNormal(ca, instr,
new MonitorExitOperator()); new MonitorExitOperator());
case opc_wide: {
switch (opcode=stream.readUnsignedByte()) {
case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload:
return createNormal
(ca, addr, 4,
new LocalLoadOperator
(types[0][opcode-opc_iload],
ca.getLocalInfo(addr, stream.readUnsignedShort())));
case opc_istore: case opc_lstore:
case opc_fstore: case opc_dstore: case opc_astore:
return createNormal
(ca, addr, 4,
new LocalStoreOperator
(types[0][opcode-opc_istore],
ca.getLocalInfo(addr+4, stream.readUnsignedShort()),
Operator.ASSIGN_OP));
case opc_iinc: {
int local = stream.readUnsignedShort();
int value = stream.readShort();
int operation = Operator.ADD_OP;
if (value < 0) {
value = -value;
operation = Operator.NEG_OP;
}
LocalInfo li = ca.getLocalInfo(addr, local);
li.setType(Type.tUInt);
return createNormal
(ca, addr, 6, new IIncOperator
(li, Integer.toString(value),
operation + Operator.OPASSIGN_OP));
}
case opc_ret:
return createRet
(ca, addr, 4,
ca.getLocalInfo(addr, stream.readUnsignedShort()));
default:
throw new ClassFormatError("Invalid wide opcode "+opcode);
}
}
case opc_multianewarray: { case opc_multianewarray: {
Type type = Type.tClassOrArray Type type = Type.tClassOrArray((String) instr.objData);
(cpool.getClassName(stream.readUnsignedShort())); type.useType();
int dimension = stream.readUnsignedByte(); int dimension = instr.intData;
return createNormal return createNormal(ca, instr,
(ca, addr, 4, new NewArrayOperator(type, dimension));
new NewArrayOperator(type, dimension));
} }
case opc_ifnull: case opc_ifnonnull: case opc_ifnull: case opc_ifnonnull:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, instr, new CompareUnaryOperator
new CompareUnaryOperator
(Type.tUObject, opcode - (opc_ifnull-Operator.COMPARE_OP))); (Type.tUObject, opcode - (opc_ifnull-Operator.COMPARE_OP)));
case opc_goto_w:
return createGoto
(ca, addr, 5, addr + stream.readInt());
case opc_jsr_w:
return createJsr
(ca, addr, 5, addr+stream.readInt());
default: default:
throw new ClassFormatError("Invalid opcode "+opcode); throw new jode.AssertError("Invalid opcode "+opcode);
} }
} }
} }

Loading…
Cancel
Save