blob: f4581ab1348946bca4dbcdf86f5f2949ee56ca15 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2008 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
* $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
*
* This file is a modified version of class org.apache.bcel.Constants
* originating from the Apache BCEL project which was provided under the
* Apache 2.0 license. Original Copyright from BCEL:
*
* Copyright 2000-2004 The Apache Software Foundation
*
* 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 org.eclipse.objectteams.otdt.internal.core.compiler.bytecode;
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
/**
* @author stephan
* @version $Id$
*/
public class OTByteCodes implements Opcodes {
/**
* Checks if a reference into the constant pool must follow
* the given byte code. If so the length of the reference
* is returned, otherwise 0. (Not complete yet)
* @param byteCode
* @return int
**/
public static int cpReferenceLength(byte byteCode) {
switch (byteCode) {
case OPC_invokeinterface: // additional parameters covered by getParamLength.
case OPC_invokevirtual:
case OPC_invokestatic:
case OPC_invokespecial:
case OPC_new:
case OPC_anewarray:
case OPC_getfield:
case OPC_getstatic:
case OPC_putfield:
case OPC_putstatic:
case OPC_instanceof:
case OPC_checkcast:
case OPC_ldc_w:
case OPC_ldc2_w:
return 2;
case OPC_ldc:
return 1;
case OPC_multianewarray:
return 2;
//throw new RuntimeException("bytecode multianewarray not supported in role methods.");
default:
return 0;
}
}
/**
* Compute the length of parameters which are not references into the constant pool.
*
* @param op
* @param code
* @param idx where op is found in code
* @param bytecodeOffset position into code, where the actual bytecode starts.
* @return length
*/
public static short getParamLength(byte op, byte[] code, int idx, int bytecodeOffset)
{
int padding, n_match;
switch (op) {
case OPC_goto: case OPC_ifeq: case OPC_ifge:
case OPC_ifle: case OPC_iflt: case OPC_jsr:
case OPC_ifne:
case OPC_ifnonnull: case OPC_ifnull:
case OPC_if_acmpeq: case OPC_if_acmpne:
case OPC_if_icmpeq: case OPC_if_icmpge:
case OPC_if_icmpgt: case OPC_if_icmple:
case OPC_if_icmplt: case OPC_if_icmpne:
case OPC_invokeinterface: // this has two non-cp parameters.
case OPC_iinc:
return 2;
case OPC_goto_w: case OPC_jsr_w:
return 4;
case OPC_aload: case OPC_astore: case OPC_dload:
case OPC_dstore: case OPC_fload: case OPC_fstore:
case OPC_iload: case OPC_istore: case OPC_lload:
case OPC_lstore: case OPC_ret: case OPC_multianewarray:
return 1;
case OPC_wide:
return 3; // swallow opcode and wide parameter
case OPC_getfield: case OPC_putfield:
case OPC_getstatic: case OPC_putstatic:
case OPC_new: case OPC_anewarray:
case OPC_checkcast: case OPC_instanceof:
case OPC_invokespecial: case OPC_invokestatic:
case OPC_invokevirtual:
case OPC_ldc_w: case OPC_ldc2_w: case OPC_ldc:
return 0; // cp index already swallowed by cpReferenceLength.
case OPC_lookupswitch:
idx++; // goto start of arguments
padding = (4 - ((idx-bytecodeOffset) % 4)) % 4; // Compute number of pad bytes
// ignore first argument "default"
n_match = getInt(code, idx+padding+4);
return (short)(8 + padding + n_match * 8); // report arguments length without opcode
case OPC_tableswitch:
idx++;
padding = (4 - ((idx-bytecodeOffset) % 4)) % 4 ;
// ignore first argument "default" at idx+padding+0
int low = getInt(code, idx+padding+4);
int high = getInt(code, idx+padding+8);
n_match = high - low + 1;
return (short)(12+padding + n_match * 4);
default:
int ib;
if(op<0) ib = op & 0x0FF;
else ib = op;
if(NO_OF_OPERANDS[ib] > 0) {
short n = 0;
for(int i=0; i < LENGTH_OF_OPERANDS[ib].length; i++)
n+=LENGTH_OF_OPERANDS[ib][i];
return n;
} else if (NO_OF_OPERANDS[ib] < 0)
throw new RuntimeException("Opcode "+op+" not supported for role methods"); //$NON-NLS-1$ //$NON-NLS-2$
}
return 0;
}
public static boolean isPush(int op) {
return (op >= OPC_aconst_null) &&
(op <= OPC_saload);
}
public static int getAloadPos(int op, int arg) {
switch(op) {
case OPC_aload_0:
case OPC_aload_1:
case OPC_aload_2:
case OPC_aload_3:
return op-OPC_aload_0;
case OPC_aload:
return arg;
}
return -1;
}
public static int getAstorePos(int op, int arg) {
switch(op) {
case OPC_astore_0:
case OPC_astore_1:
case OPC_astore_2:
case OPC_astore_3:
return op-OPC_astore_0;
case OPC_astore:
return arg;
}
return -1;
}
public static int getWord(byte[] code, int idx) {
int bp = idx;
return ((code[bp++] & 255)<< 8) + (code[bp++] & 255);
}
public static int getInt (byte[] code, int idx) {
int bp = idx;
return ((code[bp++] & 255)<< 24) + ((code[bp++] & 255)<< 16) +
((code[bp++] & 255)<< 8) + (code[bp++] & 255);
}
public static int getUnsignedByte (byte[] code, int idx) {
if (idx >= code.length) return -1;
byte b = code[idx];
// bytes are signed, unsigned value needed -> convert to int when negative
if (b < 0)
return b & 0x0ff;
else
return b;
}
public static void setWord(byte[] code, int offset, int value) {
code[offset] = (byte)(value >> 8);
code[offset+1] = (byte)value;
}
public static void setInt(byte[] code, int offset, int value) {
code[offset++] = (byte)(value >> 24);
code[offset++] = (byte)(value >> 16);
code[offset++] = (byte)(value >> 8);
code[offset++] = (byte)value;
}
public static byte[] insertWord(byte[] code, int idx, int value) {
byte[] result = new byte[code.length+2];
System.arraycopy(code, 0, result, 0, idx);
result[idx] = (byte)(value >> 8);
result[idx+1] = (byte)value;
System.arraycopy(code, idx, result, idx+2, code.length-idx);
return result;
}
/**
* Reference in big endian order.
**/
public static int getRef(int length, byte[] code, int offset) {
int ref = -1;
switch (length) {
case 1: ref = getUnsignedByte(code, offset); break;
case 2:
case 4: // [SH] also invokeinterface is followed by a two byte reference!
ref = getUnsignedByte(code, offset);
ref <<= 8;
ref |= getUnsignedByte(code, offset+1); break;
}
return ref;
}
/**
* Reference in big endian order.
**/
public static void setRef(int length, byte[] code, int cp, short newRef) {
switch (length) {
case 1: code[cp] = (byte)newRef; break;
case 2: code[cp+1] = (byte)newRef;
newRef >>= 8;
code[cp] = (byte)newRef; break;
}
}
// SH: stolen from org.apache.bcel.Constants
// (used to calculated length of byte code parameters):
static final short UNDEFINED=-1;
static final short UNPREDICTABLE=-2;
static final short RESERVED=-3;
static final short[] NO_OF_OPERANDS = {
0/*nop*/, 0/*aconst_null*/, 0/*iconst_m1*/, 0/*iconst_0*/,
0/*iconst_1*/, 0/*iconst_2*/, 0/*iconst_3*/, 0/*iconst_4*/,
0/*iconst_5*/, 0/*lconst_0*/, 0/*lconst_1*/, 0/*fconst_0*/,
0/*fconst_1*/, 0/*fconst_2*/, 0/*dconst_0*/, 0/*dconst_1*/,
1/*bipush*/, 2/*sipush*/, 1/*ldc*/, 2/*ldc_w*/, 2/*ldc2_w*/,
1/*iload*/, 1/*lload*/, 1/*fload*/, 1/*dload*/, 1/*aload*/,
0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/, 0/*iload_3*/,
0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/,
0/*fload_0*/, 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/,
0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/, 0/*dload_3*/,
0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/,
0/*iaload*/, 0/*laload*/, 0/*faload*/, 0/*daload*/,
0/*aaload*/, 0/*baload*/, 0/*caload*/, 0/*saload*/,
1/*istore*/, 1/*lstore*/, 1/*fstore*/, 1/*dstore*/,
1/*astore*/, 0/*istore_0*/, 0/*istore_1*/, 0/*istore_2*/,
0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/, 0/*lstore_2*/,
0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/,
0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/,
0/*dstore_3*/, 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/,
0/*astore_3*/, 0/*iastore*/, 0/*lastore*/, 0/*fastore*/,
0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/,
0/*sastore*/, 0/*pop*/, 0/*pop2*/, 0/*dup*/, 0/*dup_x1*/,
0/*dup_x2*/, 0/*dup2*/, 0/*dup2_x1*/, 0/*dup2_x2*/, 0/*swap*/,
0/*iadd*/, 0/*ladd*/, 0/*fadd*/, 0/*dadd*/, 0/*isub*/,
0/*lsub*/, 0/*fsub*/, 0/*dsub*/, 0/*imul*/, 0/*lmul*/,
0/*fmul*/, 0/*dmul*/, 0/*idiv*/, 0/*ldiv*/, 0/*fdiv*/,
0/*ddiv*/, 0/*irem*/, 0/*lrem*/, 0/*frem*/, 0/*drem*/,
0/*ineg*/, 0/*lneg*/, 0/*fneg*/, 0/*dneg*/, 0/*ishl*/,
0/*lshl*/, 0/*ishr*/, 0/*lshr*/, 0/*iushr*/, 0/*lushr*/,
0/*iand*/, 0/*land*/, 0/*ior*/, 0/*lor*/, 0/*ixor*/, 0/*lxor*/,
2/*iinc*/, 0/*i2l*/, 0/*i2f*/, 0/*i2d*/, 0/*l2i*/, 0/*l2f*/,
0/*l2d*/, 0/*f2i*/, 0/*f2l*/, 0/*f2d*/, 0/*d2i*/, 0/*d2l*/,
0/*d2f*/, 0/*i2b*/, 0/*i2c*/, 0/*i2s*/, 0/*lcmp*/, 0/*fcmpl*/,
0/*fcmpg*/, 0/*dcmpl*/, 0/*dcmpg*/, 2/*ifeq*/, 2/*ifne*/,
2/*iflt*/, 2/*ifge*/, 2/*ifgt*/, 2/*ifle*/, 2/*if_icmpeq*/,
2/*if_icmpne*/, 2/*if_icmplt*/, 2/*if_icmpge*/, 2/*if_icmpgt*/,
2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/, 2/*goto*/,
2/*jsr*/, 1/*ret*/, UNPREDICTABLE/*tableswitch*/, UNPREDICTABLE/*lookupswitch*/,
0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/,
0/*dreturn*/, 0/*areturn*/, 0/*return*/,
2/*getstatic*/, 2/*putstatic*/, 2/*getfield*/,
2/*putfield*/, 2/*invokevirtual*/, 2/*invokespecial*/, 2/*invokestatic*/,
4/*invokeinterface*/, UNDEFINED, 2/*new*/,
1/*newarray*/, 2/*anewarray*/,
0/*arraylength*/, 0/*athrow*/, 2/*checkcast*/,
2/*instanceof*/, 0/*monitorenter*/,
0/*monitorexit*/, UNPREDICTABLE/*wide*/, 3/*multianewarray*/,
2/*ifnull*/, 2/*ifnonnull*/, 4/*goto_w*/,
4/*jsr_w*/, 0/*breakpoint*/, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
UNDEFINED, UNDEFINED, RESERVED/*impdep1*/, RESERVED/*impdep2*/
};
static final int T_BYTE=1;
static final int T_SHORT=2;
static final int T_INT=4;
public static final short[][] LENGTH_OF_OPERANDS = {
{}/*nop*/, {}/*aconst_null*/, {}/*iconst_m1*/, {}/*iconst_0*/,
{}/*iconst_1*/, {}/*iconst_2*/, {}/*iconst_3*/, {}/*iconst_4*/,
{}/*iconst_5*/, {}/*lconst_0*/, {}/*lconst_1*/, {}/*fconst_0*/,
{}/*fconst_1*/, {}/*fconst_2*/, {}/*dconst_0*/, {}/*dconst_1*/,
{T_BYTE}/*bipush*/, {T_SHORT}/*sipush*/, {T_BYTE}/*ldc*/,
{T_SHORT}/*ldc_w*/, {T_SHORT}/*ldc2_w*/,
{T_BYTE}/*iload*/, {T_BYTE}/*lload*/, {T_BYTE}/*fload*/,
{T_BYTE}/*dload*/, {T_BYTE}/*aload*/, {}/*iload_0*/,
{}/*iload_1*/, {}/*iload_2*/, {}/*iload_3*/, {}/*lload_0*/,
{}/*lload_1*/, {}/*lload_2*/, {}/*lload_3*/, {}/*fload_0*/,
{}/*fload_1*/, {}/*fload_2*/, {}/*fload_3*/, {}/*dload_0*/,
{}/*dload_1*/, {}/*dload_2*/, {}/*dload_3*/, {}/*aload_0*/,
{}/*aload_1*/, {}/*aload_2*/, {}/*aload_3*/, {}/*iaload*/,
{}/*laload*/, {}/*faload*/, {}/*daload*/, {}/*aaload*/,
{}/*baload*/, {}/*caload*/, {}/*saload*/, {T_BYTE}/*istore*/,
{T_BYTE}/*lstore*/, {T_BYTE}/*fstore*/, {T_BYTE}/*dstore*/,
{T_BYTE}/*astore*/, {}/*istore_0*/, {}/*istore_1*/,
{}/*istore_2*/, {}/*istore_3*/, {}/*lstore_0*/, {}/*lstore_1*/,
{}/*lstore_2*/, {}/*lstore_3*/, {}/*fstore_0*/, {}/*fstore_1*/,
{}/*fstore_2*/, {}/*fstore_3*/, {}/*dstore_0*/, {}/*dstore_1*/,
{}/*dstore_2*/, {}/*dstore_3*/, {}/*astore_0*/, {}/*astore_1*/,
{}/*astore_2*/, {}/*astore_3*/, {}/*iastore*/, {}/*lastore*/,
{}/*fastore*/, {}/*dastore*/, {}/*aastore*/, {}/*bastore*/,
{}/*castore*/, {}/*sastore*/, {}/*pop*/, {}/*pop2*/, {}/*dup*/,
{}/*dup_x1*/, {}/*dup_x2*/, {}/*dup2*/, {}/*dup2_x1*/,
{}/*dup2_x2*/, {}/*swap*/, {}/*iadd*/, {}/*ladd*/, {}/*fadd*/,
{}/*dadd*/, {}/*isub*/, {}/*lsub*/, {}/*fsub*/, {}/*dsub*/,
{}/*imul*/, {}/*lmul*/, {}/*fmul*/, {}/*dmul*/, {}/*idiv*/,
{}/*ldiv*/, {}/*fdiv*/, {}/*ddiv*/, {}/*irem*/, {}/*lrem*/,
{}/*frem*/, {}/*drem*/, {}/*ineg*/, {}/*lneg*/, {}/*fneg*/,
{}/*dneg*/, {}/*ishl*/, {}/*lshl*/, {}/*ishr*/, {}/*lshr*/,
{}/*iushr*/, {}/*lushr*/, {}/*iand*/, {}/*land*/, {}/*ior*/,
{}/*lor*/, {}/*ixor*/, {}/*lxor*/, {T_BYTE, T_BYTE}/*iinc*/,
{}/*i2l*/, {}/*i2f*/, {}/*i2d*/, {}/*l2i*/, {}/*l2f*/, {}/*l2d*/,
{}/*f2i*/, {}/*f2l*/, {}/*f2d*/, {}/*d2i*/, {}/*d2l*/, {}/*d2f*/,
{}/*i2b*/, {}/*i2c*/,{}/*i2s*/, {}/*lcmp*/, {}/*fcmpl*/,
{}/*fcmpg*/, {}/*dcmpl*/, {}/*dcmpg*/, {T_SHORT}/*ifeq*/,
{T_SHORT}/*ifne*/, {T_SHORT}/*iflt*/, {T_SHORT}/*ifge*/,
{T_SHORT}/*ifgt*/, {T_SHORT}/*ifle*/, {T_SHORT}/*if_icmpeq*/,
{T_SHORT}/*if_icmpne*/, {T_SHORT}/*if_icmplt*/,
{T_SHORT}/*if_icmpge*/, {T_SHORT}/*if_icmpgt*/,
{T_SHORT}/*if_icmple*/, {T_SHORT}/*if_acmpeq*/,
{T_SHORT}/*if_acmpne*/, {T_SHORT}/*goto*/, {T_SHORT}/*jsr*/,
{T_BYTE}/*ret*/, {}/*tableswitch*/, {}/*lookupswitch*/,
{}/*ireturn*/, {}/*lreturn*/, {}/*freturn*/, {}/*dreturn*/,
{}/*areturn*/, {}/*return*/, {T_SHORT}/*getstatic*/,
{T_SHORT}/*putstatic*/, {T_SHORT}/*getfield*/,
{T_SHORT}/*putfield*/, {T_SHORT}/*invokevirtual*/,
{T_SHORT}/*invokespecial*/, {T_SHORT}/*invokestatic*/,
{T_SHORT, T_BYTE, T_BYTE}/*invokeinterface*/, {},
{T_SHORT}/*new*/, {T_BYTE}/*newarray*/,
{T_SHORT}/*anewarray*/, {}/*arraylength*/, {}/*athrow*/,
{T_SHORT}/*checkcast*/, {T_SHORT}/*instanceof*/,
{}/*monitorenter*/, {}/*monitorexit*/, {T_BYTE}/*wide*/,
{T_SHORT, T_BYTE}/*multianewarray*/, {T_SHORT}/*ifnull*/,
{T_SHORT}/*ifnonnull*/, {T_INT}/*goto_w*/, {T_INT}/*jsr_w*/,
{}/*breakpoint*/, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}/*impdep1*/, {}/*impdep2*/
};
}