
net.oneandone.mork.classfile.InstructionEncoding Maven / Gradle / Ivy
The newest version!
/*
* Copyright 1&1 Internet AG, https://github.com/1and1/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.oneandone.mork.classfile;
import net.oneandone.sushi.util.IntArrayList;
import java.io.IOException;
/**
* Encoding of an instruction.
*/
public class InstructionEncoding implements Bytecodes, Constants {
public final String name;
public final int[] args; // argument types for normal opcodes
public final InstructionType type;
public InstructionEncoding(String name, int[] args, InstructionType type) {
this.name = name;
this.args = args;
this.type = type;
}
//--
/**
* all opcodes except for tableswitch, lookupswitch and wide are considered "normal"
*/
public Instruction read(int opcode, Input src, int ofs) throws IOException {
switch (opcode) {
case WIDE:
return readWide(src, ofs);
case TABLESWITCH:
return readTableSwitch(src, ofs);
case LOOKUPSWITCH:
return readLookupSwitch(src, ofs);
default:
return readNormal(src, ofs);
}
}
private Instruction readTableSwitch(Input src, int ofs) throws IOException {
Object[] args;
IntArrayList branches;
int deflt, low, high;
int i;
int max;
src.readPad();
deflt = src.readU4();
low = src.readU4();
high = src.readU4();
max = high - low + 1;
branches = new IntArrayList();
args = new Object[4];
args[0] = new Integer(deflt);
args[1] = new Integer(low);
args[2] = new Integer(high);
args[3] = branches;
for (i = 0; i < max; i++) {
branches.add(src.readU4());
}
return new Instruction(ofs, type, args);
}
private Instruction readLookupSwitch(Input src, int ofs) throws IOException {
int i;
int count;
int deflt;
Object[] args;
IntArrayList keys;
IntArrayList branches;
src.readPad();
deflt = src.readU4();
count = src.readU4();
keys = new IntArrayList();
branches = new IntArrayList();
args = new Object[3];
args[0] = new Integer(deflt);
args[1] = keys;
args[2] = branches;
for (i = 0; i < count; i++) {
keys.add(src.readU4());
branches.add(src.readU4());
}
return new Instruction(ofs, type, args);
}
private static Instruction readWide(Input src, int ofs) throws IOException {
int b;
Object[] args;
b = src.readU1();
switch (b) {
case IINC:
args = new Object[2];
args[0] = (int) src.readU2();
args[1] = src.readS2();
break;
case ILOAD:
case FLOAD:
case ALOAD:
case LLOAD:
case DLOAD:
case ISTORE:
case FSTORE:
case ASTORE:
case LSTORE:
case DSTORE:
case RET:
// TODO: don't hard-wire constants
args = new Object[] { (int) src.readU2() };
break;
default:
throw new RuntimeException("illegal iinc");
}
return new Instruction(ofs, Set.TYPES[b], args);
}
private Instruction readNormal(Input src, int ofs) throws IOException {
Object[] argValues;
int i;
argValues = new Object[args.length];
for (i = 0; i < args.length; i++) {
argValues[i] = readArg(src, args[i]);
}
return new Instruction(ofs, type, argValues);
}
private static Object readArg(Input src, int argType) throws IOException {
MethodRef ifc;
int tmp;
switch (argType) {
case AE_U1:
return new Integer(src.readU1());
case AE_S1:
return new Integer(src.readS1());
case AE_U2:
return new Integer(src.readU2());
case AE_S2:
return new Integer(src.readS2());
case AE_U4:
return new Integer(src.readU4());
case AE_REFTYPEREF:
return src.readClassRef();
case AE_FIELDREF:
return src.readFieldRef();
case AE_IFMETHOD:
ifc = src.readInterfaceMethodRef();
tmp = src.readU1();
if (tmp != 1 + ifc.argSize()) { // 1 for "this"
throw new RuntimeException(
ifc + ": illegal ifc arg size: " + tmp);
}
if (src.readU1() != 0) {
throw new RuntimeException("0 expected");
}
return ifc;
case AE_METHODREF:
return src.readClassMethodRef();
case AE_CNST:
// TODO: check type
return src.readShortConstant();
case AE_CNST_W:
case AE_CNST2_W:
// TODO: check type
return src.readConstant();
default:
if (argType <= AE_I_LAST) {
return IMPLICIT[argType];
} else {
throw new IllegalArgumentException("illegal arg type: " + argType);
}
}
}
@Override
public String toString() {
StringBuilder result;
int i;
result = new StringBuilder();
result.append(name);
for (i = 0; i < args.length; i++) {
result.append(' ');
result.append("" + args[i]);
}
return result.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy